Ошибки утечки памяти valgrind при использовании pthread_create
Я пишу программу с использованием библиотеки pthread. Когда я запускаю свою программу с командой valgrind --leak-check=full
, я получаю следующее описание ошибки:
==11784==
==11784== **HEAP SUMMARY:**
==11784== in use at exit: 4,952 bytes in 18 blocks
==11784== total heap usage: 1,059 allocs, 1,041 frees, 51,864 bytes allocated
==11784==
==11784== **288 bytes** in 1 blocks are possibly lost in loss record 2 of 3
==11784== at 0x4C2380C: calloc (vg_replace_malloc.c:467)
==11784== by 0x4010D2E: _dl_allocate_tls (dl-tls.c:300)
==11784== by 0x55DC218: **pthread_create**@@GLIBC_2.2.5 (allocatestack.c:570)
==11784== by 0x401BC0: initdevice(char*) (in /a/fr-01/vol/home/stud/lim/workspace /Ex3/l)
==11784== by 0x406D05: main (in /a/fr-01/vol/home/stud/lim/workspace/Ex3/l)
==11784==
==11784== **4,608 bytes** in 16 blocks are possibly lost in loss record 3 of 3
==11784== at 0x4C2380C: calloc (vg_replace_malloc.c:467)
==11784== by 0x4010D2E: _dl_allocate_tls (dl-tls.c:300)
==11784== by 0x55DC218: **pthread_create**@@GLIBC_2.2.5 (allocatestack.c:570)
==11784== by 0x40268F: write2device(char*, int) (in /a/fr-01/vol/home/stud/lim/workspace/Ex3/l)
==11784== by 0x406D7B: main (in /a/fr-01/vol/home/stud/lim/workspace/Ex3/l)
==11784==
==11784== **LEAK SUMMARY:**
==11784== definitely lost: 0 bytes in 0 blocks
==11784== indirectly lost: 0 bytes in 0 blocks
==11784== possibly lost: 4,896 bytes in 17 blocks
==11784== still reachable: 56 bytes in 1 blocks
==11784== suppressed: 0 bytes in 0 blocks
==11784== Reachable blocks (those to which a pointer was found) are not shown.
==11784== To see them, rerun with: --leak-check=full --show-reachable=yes
==11784==
==11784== For counts of detected and suppressed errors, rerun with: -v
==11784== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 4 from 4)
Каждый раз, когда я вызываю pthread_create
с определенной функцией - я вызываю функцию pthread_exit
в конце функции. Итак, после проверки это не проблема, в чем может быть проблема?
Ответы
Ответ 1
Ресурсы потоков не сразу освобождаются при завершении, если только
поток был создан с атрибутом detach state
, установленным для
PTHREAD_CREATE_DETACHED
, или если pthread_detach
вызывается для
его pthread_t
.
Нераскрытый поток будет оставаться в состоянии завершения до тех пор, пока его идентификатор не будет передан в pthread_join
или pthread_detach
.
Чтобы подвести итог, у вас есть три варианта:
- создайте свой поток с отключенным набором атрибутов (атрибут PTHREAD_CREATE_DETACHED)
- Отсоедините свой поток после создания (путем вызова
pthread_detach
) или
- Присоединитесь к завершенным потокам, чтобы их переработать (вызывая
pthread_join
).
Hth.
Ответ 2
Вы можете перевести поток в отключенное состояние, чтобы избежать утечки памяти, если поток не должен быть присоединен (или просто истекает сам по себе).
Чтобы явно создать поток как присоединяемый или отсоединенный, используется аргумент attr в подпрограмме pthread_create(). Типичный четырехэтапный процесс:
- Объявите переменную атрибута pthread типа данных
pthread_attr_t
- Инициализируйте переменную атрибута с помощью
pthread_attr_init()
- Установите статус отсоединенного атрибута с помощью
pthread_attr_setdetachstate()
- Когда это будет сделано, освободите библиотечные ресурсы, используемые атрибутом с
pthread_attr_destroy()
Ответ 3
когда не работает с присоединяемыми потоками, входящий поток должен вызывать pthread_detach(pthread_self())
чтобы освободить все его ресурсы.
Ответ 4
В дополнение к правильным ответам, предоставленным вам другими пользователями, я предлагаю вам прочитать следующее:
Отслеживание утечки памяти в многопоточном приложении C
Ответ 5
Обратите внимание, что поведение pthread_create по умолчанию "joinable" NOT DETACHED.
Поэтому некоторые ресурсы ОС по-прежнему будут оставаться в процессе после завершения pthread, что приведет к появлению zombie pthread и приведет к увеличению использования VIRTUAL/резидентной памяти.
В четырех упомянутых выше решениях будет устранена эта проблема.
Однако, если вы потоки многолетних, это может быть не очень необходимо.
например, если pthread проживает всю жизнь процесса.