Утечка стека потоков через рекурсивную функцию - PullRequest
1 голос
/ 28 декабря 2010

У меня есть следующий сценарий, в реализации C с pthreads:

Основной поток (T1) создает другой поток (T2), который ожидает событие.

В случае события T2 вызывает функцию обхода дерева рекурсивную функцию, которая принимает указатель на функцию для выполнения действия на узле дерева. Во время обхода дерева, если узел найден, запускается указатель fn, который создает поток (T3), обслуживает узел и, как предполагается, обычно вымирает.

Я наблюдаю огромную утечку памяти из стека Т3. Вальгринд говорит мне, что

==9251== 2,720 bytes in 20 blocks are possibly lost in loss record 142 of 157

==9251==    at 0x402425F: calloc (vg_replace_malloc.c:467)

==9251==    by 0x4010CDB: _dl_allocate_tls (dl-tls.c:300)

==9251==    by 0x403A2E2: pthread_create@@GLIBC_2.1 (allocatestack.c:561)

==9251==    by 0x80571CC: serviceNode (NodeHndlr.c:432)

==9251==    by 0x804AD88: preOrderTpTraversal (treefunct.c:503)

==9251==    by 0x804AE01: preOrderTpTraversal (treefunct.c:513)

==9251==    by 0x804AE01: preOrderTpTraversal (treefunct.c:513)

==9251==    by 0x804AE01: preOrderTpTraversal (treefunct.c:513)

==9251==    by 0x8057450: serviceproc (NodeHndlr.c:519)

==9251==    by 0x403996D: start_thread (pthread_create.c:300)

==9251==    by 0x411AA4D: clone (clone.S:130)

Здесь serviceproc - это T2 serviceNode - указатель на функцию для узла.

Таким образом, в конечном итоге в системе заканчивается vm, и создание потока завершается с ошибкой с кодом ошибки = 11 (недостаточно ресурсов)

Мой вопрос заключается в том, что как только T3 (созданный serviceNode) выходит нормально , не должен ли стек потоков автоматически собираться мусором, или я что-то здесь упустил. ?

Редактировать: или проблема возникла из-за срабатывания указателя функции?

Ответы [ 2 ]

4 голосов
/ 29 декабря 2010

В большинстве реализаций pthreads вы потеряете часть памяти при выходе из потока, если только вы не выполните:

  • Вызовите pthread_join () этого потока

    или

  • Создать поток как отдельный поток, вызвав pthread_detach () или как атрибут pthread_create

Убедитесь, что вы делаете одно из вышеперечисленных.

0 голосов
/ 29 декабря 2010

Вы уверены, что ваша главная проблема - утечка памяти? Мне кажется, что вы создаете слишком много тем. Если вы создадите новый поток в рекурсивно вызываемой функции, вы можете получить тысячи потоков. Это может легко убить ваше приложение. Просто подумайте о памяти, которая необходима для стека каждого потока.

...