c pthreads+;valgrind=内存泄漏:为什么?
我开始使用C语言中的pthreads,我也是一个狂热的人,我尽可能地将我的代码写得“无bug” 尽管努力格外小心,但valgrind告诉我,无论天气如何,我都在泄漏内存:c pthreads+;valgrind=内存泄漏:为什么?,c,memory-leaks,pthreads,valgrind,C,Memory Leaks,Pthreads,Valgrind,我开始使用C语言中的pthreads,我也是一个狂热的人,我尽可能地将我的代码写得“无bug” 尽管努力格外小心,但valgrind告诉我,无论天气如何,我都在泄漏内存: 我创建完成后加入的可加入线程(代码段1) 我创建了可连接的线程,并在创建后将其分离(代码段2) 我创建分离的线程(代码段3) 我知道这一点已经讨论过了(见,也有),但我仍然很好奇: 为什么在某些跑步中我最终没有出错 为什么在处理分离的线程时总的mallocs()似乎是随机数 当线程分离时,会出现错误,导致未定义的行为 主要有以
struct args_for_job_t args[MAX_THREADS];
您可以将指针交给工作线程
然后main()到达这一部分
pthread_exit(NULL);
main()不再存在,但是您仍然可能有工作线程,它访问上面的args
数组,该数组位于main()的堆栈上,而main()已经不存在了。
在某些运行中,您的工作线程可能在main()结束之前全部完成,但在其他运行中不会完成。valgrind的输出是什么?(旁白:不需要在该代码中的任何地方使用
pthread\u exit
,您只需返回0;
);而不是main()中的pthread_exit()。此外,我还为joined()代码段添加了valgrind输出,增加了main()的完成时间,正如nos清除了我的第二个和第三个问题所建议的那样。这不是真正的内存泄漏,所有内存仍然可以访问抱歉,我关于pthread_exit
的评论只与代码段1相关,在那里它是无用的(因为你加入了线程).在代码段2和3中,在main
末尾调用它是正确的。同意,这不是真正意义上的内存泄漏,根本不是错误,但让我感到不安的是,为什么在某些运行中,所有内容都被正确释放,而在大多数运行中则没有。谢谢,不,我怀疑这种行为,但想再次检查。问题是,我还尝试了在pthread_exit(NULL)(或者按照Jonathan的建议返回0)之前添加一个计时器(usleep()),它仍然是随机行为。我一直认为使用pthread_exit()而不是return将告诉main()线程挂起,直到所有工作线程都完成为止(这正是pthread_join()所做的).I stand correct,我使用分离的线程将睡眠时间从10000增加到100000,似乎所有内存泄漏都消失了,这为所有线程留出了足够的时间在main()之前完成终止。很抱歉,您是对的,main
中的pthread\u exit
导致它等待。在其他线程和代码段1中对pthread\u exit
的调用是冗余的。如果我将等待时间增加为“强制”,则在处理分离的线程时,它似乎不会导致它在main()中等待等待不会有错误。我将pthread_exit()保留在分离线程中的原因是尽量减少从一个版本到另一个版本的代码更改,但我同意这是多余的,我将在代码段中修复它。谢谢!事实上,我意识到我在发布的版本中删除了它们,我添加了“return NULL;”只是为了它,但它确实是多余的。我仍然希望将pthread_exit()保留在联接版本中,因为我将依赖返回状态来执行其他工作。
/* Running this multiple times with valgrind, I sometimes end with :
- no errors (proper malloc/free balance)
- 1 extra malloc vs free (most frequently)
Most surprisingly, it seems there is a random amount of overall mallocs
*/
#include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS macros & the likes */
#include <stdio.h> /* printf() & the likes */
#include <pthread.h> /* test subject */
#define MAX_THREADS 100 /* Number of threads */
pthread_attr_t tattr; /* Thread attribute */
pthread_t workers[MAX_THREADS]; /* All the threads spawned by the main() thread */
/* A mock container structure to pass arguments around */
struct args_for_job_t {
int tid;
};
/* The job each worker will perform upon creation */
void *job(void *arg)
{
/* Cast arguments in a proper container */
struct args_for_job_t *container;
container = (struct args_for_job_t *)arg;
/* A mock job */
printf("[TID - %d]\n", container->tid);
/* For the sake of returning something, not necessary */
return NULL;
}
int main ()
{
int return_code; /* Will hold return codes */
int tid; /* Thread id */
struct args_for_job_t args[MAX_THREADS]; /* For thread safeness */
/* Initialize and set thread detached attribute */
pthread_attr_init(&tattr);
pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
/* Spawn detached threads */
for (tid = 0; tid < MAX_THREADS; tid++)
{
args[tid].tid = tid;
return_code = pthread_create(&workers[tid], &tattr, job, (void *)(&args[tid]));
if (return_code != 0) { printf("[ERROR] Thread creation failed\n"); return EXIT_FAILURE; }
}
/* Free thread attribute */
pthread_attr_destroy(&tattr);
/* Delay main() completion until all detached threads finish their jobs. */
usleep(100000);
return EXIT_SUCCESS;
}
==27802==
==27802== HEAP SUMMARY:
==27802== in use at exit: 1,558 bytes in 4 blocks
==27802== total heap usage: 105 allocs, 101 frees, 28,814 bytes allocated
==27802==
==27802== Searching for pointers to 4 not-freed blocks
==27802== Checked 104,360 bytes
==27802==
==27802== 36 bytes in 1 blocks are still reachable in loss record 1 of 4
==27802== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==27802== by 0x400894D: _dl_map_object (dl-load.c:162)
==27802== by 0x401384A: dl_open_worker (dl-open.c:225)
==27802== by 0x400F175: _dl_catch_error (dl-error.c:178)
==27802== by 0x4013319: _dl_open (dl-open.c:639)
==27802== by 0x517F601: do_dlopen (dl-libc.c:89)
==27802== by 0x400F175: _dl_catch_error (dl-error.c:178)
==27802== by 0x517F6C3: __libc_dlopen_mode (dl-libc.c:48)
==27802== by 0x4E423BB: pthread_cancel_init (unwind-forcedunwind.c:53)
==27802== by 0x4E4257B: _Unwind_ForcedUnwind (unwind-forcedunwind.c:130)
==27802== by 0x4E4069F: __pthread_unwind (unwind.c:130)
==27802== by 0x4E3AFF4: pthread_exit (pthreadP.h:265)
==27802==
==27802== 36 bytes in 1 blocks are still reachable in loss record 2 of 4
==27802== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==27802== by 0x400B7EC: _dl_new_object (dl-object.c:161)
==27802== by 0x4006805: _dl_map_object_from_fd (dl-load.c:1051)
==27802== by 0x4008699: _dl_map_object (dl-load.c:2568)
==27802== by 0x401384A: dl_open_worker (dl-open.c:225)
==27802== by 0x400F175: _dl_catch_error (dl-error.c:178)
==27802== by 0x4013319: _dl_open (dl-open.c:639)
==27802== by 0x517F601: do_dlopen (dl-libc.c:89)
==27802== by 0x400F175: _dl_catch_error (dl-error.c:178)
==27802== by 0x517F6C3: __libc_dlopen_mode (dl-libc.c:48)
==27802== by 0x4E423BB: pthread_cancel_init (unwind-forcedunwind.c:53)
==27802== by 0x4E4257B: _Unwind_ForcedUnwind (unwind-forcedunwind.c:130)
==27802==
==27802== 312 bytes in 1 blocks are still reachable in loss record 3 of 4
==27802== at 0x4C29DB4: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==27802== by 0x4010B59: _dl_check_map_versions (dl-version.c:300)
==27802== by 0x4013E1F: dl_open_worker (dl-open.c:268)
==27802== by 0x400F175: _dl_catch_error (dl-error.c:178)
==27802== by 0x4013319: _dl_open (dl-open.c:639)
==27802== by 0x517F601: do_dlopen (dl-libc.c:89)
==27802== by 0x400F175: _dl_catch_error (dl-error.c:178)
==27802== by 0x517F6C3: __libc_dlopen_mode (dl-libc.c:48)
==27802== by 0x4E423BB: pthread_cancel_init (unwind-forcedunwind.c:53)
==27802== by 0x4E4257B: _Unwind_ForcedUnwind (unwind-forcedunwind.c:130)
==27802== by 0x4E4069F: __pthread_unwind (unwind.c:130)
==27802== by 0x4E3AFF4: pthread_exit (pthreadP.h:265)
==27802==
==27802== 1,174 bytes in 1 blocks are still reachable in loss record 4 of 4
==27802== at 0x4C29DB4: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==27802== by 0x400B57D: _dl_new_object (dl-object.c:77)
==27802== by 0x4006805: _dl_map_object_from_fd (dl-load.c:1051)
==27802== by 0x4008699: _dl_map_object (dl-load.c:2568)
==27802== by 0x401384A: dl_open_worker (dl-open.c:225)
==27802== by 0x400F175: _dl_catch_error (dl-error.c:178)
==27802== by 0x4013319: _dl_open (dl-open.c:639)
==27802== by 0x517F601: do_dlopen (dl-libc.c:89)
==27802== by 0x400F175: _dl_catch_error (dl-error.c:178)
==27802== by 0x517F6C3: __libc_dlopen_mode (dl-libc.c:48)
==27802== by 0x4E423BB: pthread_cancel_init (unwind-forcedunwind.c:53)
==27802== by 0x4E4257B: _Unwind_ForcedUnwind (unwind-forcedunwind.c:130)
==27802==
==27802== LEAK SUMMARY:
==27802== definitely lost: 0 bytes in 0 blocks
==27802== indirectly lost: 0 bytes in 0 blocks
==27802== possibly lost: 0 bytes in 0 blocks
==27802== still reachable: 1,558 bytes in 4 blocks
==27802== suppressed: 0 bytes in 0 blocks
==27802==
==27802== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
--27802--
--27802-- used_suppression: 2 dl-hack3-cond-1
==27802==
==27802== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
--29170-- Discarding syms at 0x64168d0-0x6426198 in /lib/x86_64-linux-gnu/libgcc_s.so.1 due to munmap()
==29170==
==29170== HEAP SUMMARY:
==29170== in use at exit: 0 bytes in 0 blocks
==29170== total heap usage: 105 allocs, 105 frees, 28,814 bytes allocated
==29170==
==29170== All heap blocks were freed -- no leaks are possible
==29170==
==29170== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
--29170--
--29170-- used_suppression: 2 dl-hack3-cond-1
==29170==
==29170== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
struct args_for_job_t args[MAX_THREADS];
pthread_exit(NULL);