即使在 pthread_detach 之后仍会泄漏

Getting Leaks Even After pthread_detach

如果我使用 pthread_detach 从副线程终止整个程序,我正在尝试使自清理线程代码释放 pthread_t 资源,但我仍然从 valgrind 收到内存泄漏报告可能丢失字节。这是我的示例代码片段:

pthread_t main_thread;
pthread_t second_thread;

void* thread_func() {
    pthread_detach(pthread_self());
    exit(0);
}

int main() {
    main_thread = pthread_self(); // record main thread in case needed later
    pthread_create(&second_thread, NULL, thread_func, NULL);
    while(1); // making main thread wait using a busy-wait (in case pthread_join) interferes
              // with pthread_detach (that's another question though: does pthread_join called
              // from another thread overlaps with pthread_detach from the same thread?)


}


谁能帮我指出我忘记释放任何已分配资源的地方?

使用 pthread_detach() 分离线程会通知 pthreads 库与此线程关联的资源可以在线程终止后 被释放 。但是,您正在退出整个过程,因此 Valgrind 抱怨资源泄漏。尽管在进程退出时,所有资源都将在现代操作系统上清理,但 Valgrind 非常挑剔。

因此,如果您从 thread_func() 调用 pthread_exit(NULL);return NULL;,而不是调用 exit() - 退出整个进程而不仅仅是调用线程,您应该看到pthreads 库释放分配的资源。

does pthread_join called from another thread overlaps with pthread_detach from the same thread?

您不能加入已分离的线程(它是使用分离的属性集创建的或使用 pthread_detach() 分离的)。 pthread_detach() 的文档说它是 未指定的:

Attempting to detach an already detached thread results in unspecified behavior.

所以,对于我几天前遇到的问题,我刚刚找到了一个惊人的解决方案,我想分享它。

提醒一下原来的问题是什么:问题是如何在调用完整进程退出后清除线程泄漏(这不会是生产代码中的实际泄漏,但这只是为了使 valgrind,例如,快乐!!)。

所以我想到的解决方案是:

通过只为 "main" 线程创建一个线程,使主线程与任何其他线程一样(我知道,这会增加内存使用量,而且效率不会很高)。实际的主线程将不断检查从任何线程发送的任何退出信号,如果是,则清理所有线程并退出。其他线程将在需要时发送退出信号,并等待实际主线程清理它们(包括包含预期主线程代码的模型 "main" 线程)。

这是一个伪代码来举例说明我上面提到的内容:

threadId1;
threadId2;
mainThreadId;
willExit = false;
exitStatusCode;
mainThreadArgs;

exit_cleanup(exitStatusCodeArg) {
    exitStatusCode = exitStatusArg;
    willExit = true;
    while(true);
}

threadFunc1() {
    // Example thread code 1
    exit_cleanup(0);
}

threadFunc2() {
    // Example thread code 2
    if (/*some error*/)
        exit_cleanup(-1);
}

mainThreadFunc() {
    // some code (could be long, and may create side threads here)

    // by default, main thread should call exit_cleanup(0) at the end, as
    // exiting the main thread should also cancel all running threads
    exit_cleanup(0);
}

cleanUp() {
    while (willExit != false);
    for (all thread saved globally) {
        cancel and join current thread;
    }
    exit(exitStatusCode);
}

main(args) {
    mainThreadArgs = args;
    create_thread(mainThreadId, mainThreadFunc);
    cleanUp();
}



从上面的代码中,我看不出为什么 valgrind 或任何其他内存泄漏检查器会抱怨任何 "still reachable" 或 "possibly lost" 泄漏。

感谢对我的解决方案的任何更正!!