即使在 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" 泄漏。
感谢对我的解决方案的任何更正!!
如果我使用 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" 泄漏。
感谢对我的解决方案的任何更正!!