【发布时间】:2020-03-18 22:00:54
【问题描述】:
代码:
http://man7.org/tlpi/code/online/book/threads/strerror_tsd.c
static void /* Free thread-specific data buffer */
destructor(void *buf)
{
free(buf);
}
static void /* One-time key creation function */
createKey(void)
{
int s;
/* Allocate a unique thread-specific data key and save the address
of the destructor for thread-specific data buffers */
s = pthread_key_create(&strerrorKey, destructor);
if (s != 0)
errExitEN(s, "pthread_key_create");
}
char *
strerror(int err)
{
int s;
char *buf;
/* Make first caller allocate key for thread-specific data */
s = pthread_once(&once, createKey);
if (s != 0)
errExitEN(s, "pthread_once");
buf = pthread_getspecific(strerrorKey);
if (buf == NULL) { /* If first call from this thread, allocate
buffer for thread, and save its location */
buf = malloc(MAX_ERROR_LEN);
if (buf == NULL)
errExit("malloc");
s = pthread_setspecific(strerrorKey, buf);
if (s != 0)
errExitEN(s, "pthread_setspecific");
}
if (err < 0 || err >= _sys_nerr || _sys_errlist[err] == NULL) {
snprintf(buf, MAX_ERROR_LEN, "Unknown error %d", err);
} else {
strncpy(buf, _sys_errlist[err], MAX_ERROR_LEN - 1);
buf[MAX_ERROR_LEN - 1] = '\0'; /* Ensure null termination */
}
return buf;
}
http://man7.org/tlpi/code/online/dist/threads/strerror_test.c
static void *
threadFunc(void *arg)
{
char *str;
printf("Other thread about to call strerror()\n");
str = strerror(EPERM);
printf("Other thread: str (%p) = %s\n", str, str);
return NULL;
}
int
main(int argc, char *argv[])
{
pthread_t t;
int s;
char *str;
str = strerror(EINVAL);
printf("Main thread has called strerror()\n");
s = pthread_create(&t, NULL, threadFunc, NULL);
if (s != 0)
errExitEN(s, "pthread_create");
s = pthread_join(t, NULL);
if (s != 0)
errExitEN(s, "pthread_join");
/* If strerror() is not thread-safe, then the output of this printf() be
the same as that produced by the analogous printf() in threadFunc() */
printf("Main thread: str (%p) = %s\n", str, str);
exit(EXIT_SUCCESS);
}
问题:
int pthread_key_create(pthread_key_t *key, void (destructor)(void *));
strerror 的实现使用线程特定的数据。在终止具有与键关联的非 NULL 值的线程时,
析构函数由 Pthreads API 自动调用,并给出
值作为它的论据。根据我的测试,调用strerror 的主线程不会触发destructor,但子线程会。我想知道为什么?
谢谢
【问题讨论】:
-
标题不清楚。主线程中没有调用析构函数?
-
当我说析构函数时,我的意思是传递给 pthread_key_create(&strerrorKey, destructor) 的函数
-
@q0987,我认为托尼的问题是关于“但主线程”的预期含义。即使没有,这也是我想知道的。
-
我的第二个问题是关于为什么你会期望析构函数永远被调用,尤其是为什么你期望调用
strerror()会产生这样的结果效果。您的main()和threadFunc()似乎都没有直接或间接地做任何会产生这种结果的事情。我希望您代表的成员非常清楚我们需要minimal reproducible example,以及如何准备一个好的。 -
@JohnBollinger 这正是我要问的。