Утечка памяти в Windows pthread. `pthread_join` не освобождает память

Простой тест:

void testMemoryLeak_PthreadCreateJoin(void)
{
   auto taskFunction = [](void*args) -> void*
   {
      return nullptr;
   };
   pthread_t pth;
   int err = pthread_create(&pth, /*attr*/nullptr, taskFunction, /*args*/nullptr);
   pthread_join(pth, nullptr);
}

void main(void)
{
   _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
   testMemoryLeak_PthreadCreateJoin();
   testMemoryLeak_PthreadCreateJoin();
   testMemoryLeak_PthreadCreateJoin();
   testMemoryLeak_PthreadCreateJoin();
}

Здесь сказано:

Поток — это выделенный ресурс, и вы не освободили его перед выходом. Вы должны позвонить pthread_join; это также устранит необходимость в вашем хакерском и неправильном цикле сна.

Вполне возможно, что даже после того, как вы исправите это, valgrind все еще будет видеть «утечку», поскольку некоторые реализации потоков POSIX (я предполагаю, что вы используете glibc/NPTL) кэшируют и повторно используют ресурсы потока, а не освобождают их полностью. Я не уверен, работает ли valgrind с этим или нет.

Но я уже использую pthread_join. Я использую VS2015 и его анализатор кучи. Может ли проблема быть в pthread моей конкретной реализации? Я использую PAL от Dongsheng Song

Вызывает утечку памяти:

Detected memory leaks!
Dumping objects ->
{104} normal block at 0x007742C0, 24 bytes long.
 Data: <     X          > D8 00 00 00 E0 58 20 00 00 00 00 00 00 00 00 00 
{101} normal block at 0x00774398, 24 bytes long.
 Data: <     X          > D8 00 00 00 E0 58 20 00 00 00 00 00 00 00 00 00 
{98} normal block at 0x00774038, 24 bytes long.
 Data: <     X          > D8 00 00 00 E0 58 20 00 00 00 00 00 00 00 00 00 
{95} normal block at 0x00774860, 24 bytes long.
 Data: <     X          > D8 00 00 00 E0 58 20 00 00 00 00 00 00 00 00 00 
Object dump complete.

24 байта для каждого потока. pthread_join() должен был освободить память, но этого не произошло. Поэтому я полагаю, что реализация глючит. Пожалуйста, подтвердите или опровергните это.


person kyb    schedule 09.12.2016    source источник


Ответы (1)


Если вы хотите отследить точку выделения, см. _CrtSetAllocHook — вы можете установите свой собственный крючок распределения и проверьте стек на наличие блоков, которые, как вы знаете, будут утекать. Однако для того, чтобы это принесло какие-либо преимущества, вам потребуется отладочная версия реализации POSIX, чтобы правильно видеть стек. Тогда можно попробовать и действительно пропатчить, чтобы память освободилась.

person Rudolfs Bundulis    schedule 09.12.2016
comment
Я думаю, что CrtSetDbgFlag достаточно для анализа. Я не буду отлаживать pthreads. Достаточно знать, что это глючит или я где-то допускаю ошибку. - person kyb; 09.12.2016
comment
@kyb хорошо, если вы хотите разобраться в своих ошибках, тогда CrtSetAllocHook покажет, выделены ли неисправные блоки памяти из вашего стека или из библиотеки pthreads. - person Rudolfs Bundulis; 09.12.2016