C에서 pthreads를 시작하려고합니다. 또한 "버그가 없다"라고 코드를 작성하는 광적인 사람입니다.c pthreads + valgrind = 메모리 누수 : 이유가 무엇입니까?
- 내가이 완료되면 가입 결합 가능한 스레드를 생성 (코드 1)
- 내가 조인 생성 : 추가 I 메모리가 누수하고 조심, Valgrind의 날을 말하고, 날씨에 관계없이려고 노력에도 불구하고
내가 생성 한 후 분리 스레드 (코드 2)
- 내가 분리 된 스레드를 생성 (코드 3) 나는이 이미 논의 된 알
(012,338,248,919,876 참조, this 또한 this),하지만 난에 관해서는 여전히 궁금 :
나는 오류없이 결국 특정 실행에- 이유는 무엇입니까?
- 분리 된 스레드를 처리 할 때 전체 mallocs()가 무작위로 나타나는 이유는 무엇입니까? < < 님이 제공 한 답변 nosed by main()에 추가 지연이있는 코드 스 니펫
- 분리 된 스레드를 처리 할 때도 "메모리 누수가 지속되는 이유는 무엇입니까? < < 같은 2
내가 이전에 응답하고 Valgrind의 추적에서 알고있는 것처럼로는 pthread_create()는, 따라서 몇 가지 누락을 필요 스레드가 사용하는 스택을 확장하고 시간에 그것을 재사용, 근본 원인이다 해방한다. 그러나 명확하지 않은 것은 실행 실행에 의존하는 이유와 분리 된 스레드를 만들 때 발생하는 이유입니다. 특정 답변, 주석 및 사람으로부터 보았을 때 분리 된 스레드의 자원은 스레드 완료시 해방됩니다. 나는이 문제를 해결하기 위해 다양한 조정을 시도했다. (메인 스레드가 끝나기 전에 각각의 스레드가 끝나기 전에 잠자기 시간을 추가하고, 스택 크기를 늘려서 더 많은 "작업"을 추가했다.)하지만 변경되지 않았다. 최종 결과. 또한 분리 된 쓰레드를 처리 할 때 전체 "mallocs()"가 무작위로 나타나는 이유는 무엇입니까? valgrind는 분리 된 쓰레드를 추적하지 못합니까? 이것은 또한 스택 크기에 의존하지 않는 것처럼 보입니다.
제공된 코드는 스레드 관리에 대한 조인 가능/조인 (join) 접근 방식이 더 적합한 것으로 보이는 관리자/근로자 모델의 모의 예입니다.
깨달음을 주셔서 감사합니다. 또한 이러한 (주석이 많은) 코드 스 니펫이 pthreads를 시작하고자하는 사람들에게 도움이되기를 바랍니다.
- swappy
PS sys 인 정보 : 데비안 64 비트 아치에 GCC는
코드 1 (결합 가능한 스레드가 결합) 니펫을 :
/* Running this multiple times with valgrind, I sometimes end with :
- no errors (proper malloc/free balance)
- 4 extra malloc vs free (most frequently)
The number of mallocs() is more conservative and depends on the number of threads.
*/
#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;
int status;
};
/* 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);
/* Properly exit with status code tid */
pthread_exit((void *)(&container->status));
}
int main()
{
int return_code; /* Will hold return codes */
void *return_status; /* Will hold return status */
int tid; /* Thread id */
struct args_for_job_t args[MAX_THREADS]; /* For thread safeness */
/* Initialize and set thread joinable attribute */
pthread_attr_init(&tattr);
pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE);
/* Spawn detached threads */
for (tid = 0; tid < MAX_THREADS; tid++)
{
args[tid].tid = tid;
args[tid].status = 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);
/* Properly join() all workers before completion */
for(tid = 0; tid < MAX_THREADS; tid++)
{
return_code = pthread_join(workers[tid], &return_status);
if (return_code != 0)
{
printf("[ERROR] Return code from pthread_join() is %d\n", return_code);
return EXIT_FAILURE;
}
printf("Thread %d joined with return status %d\n", tid, *(int *)return_status);
}
return EXIT_SUCCESS;
}
코드 2 (분리 된 스레드를 니펫을 생성 후) :
/* 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 */
#include <unistd.h>
#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 joinable attribute */
pthread_attr_init(&tattr);
pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE);
/* 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; }
/* Detach worker after creation */
pthread_detach(workers[tid]);
}
/* Free thread attribute */
pthread_attr_destroy(&tattr);
/* Delay main() completion until all detached threads finish their jobs. */
usleep(100000);
return EXIT_SUCCESS;
}
코드 3 (작성시 분리 된 스레드) 니펫 :
/* 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;
}
코드 1 (결합 스레드 & MEM 리크) 코드에 대한
==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)
Valgrind의 출력
Valgrind의 출력 1 (mem-leak 없음, 나중에 약간 실행)
--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)
valgrind 출력이란 무엇입니까? (Aside : 그 코드에서'pthread_exit'를 사용할 필요가 없습니다. 대신'return 0;'을 사용할 수 있습니다.) –
반환 값 0을 적용하여 수정했습니다. main()에서 pthread_exit() 대신에. 또한 joined() 코드 스 니펫에 valgrind 출력을 추가하여 두 번째 및 세 번째 질문을 지우지 않은 main()의 완료 시간을 늘 렸습니다. – swappy
그건 실제로 메모리 누수가 아니야, 모든 메모리는 여전히 접근 가능합니다. –