天天看点

用valgrind调试pthread_create引起的内存泄漏------顺便熟悉下线程的joinable和detached属性

       valgrind的安装和调试很简单, 之前博文多次介绍(如果是ubuntu, 直接apt安装更简单, 一条命令搞定)。 最近遇到一个让人颇为难解的内存泄漏问题, 下面我们来抽取核心逻辑, 简单来说下:

       先看看这段程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

void* threadFunc(void* p)  
{  
	char szTest[1024 * 32] = {0};
    return NULL;  
}  
 
int main(void)
{
	pthread_t id;  
    pthread_create (&id, NULL, threadFunc, NULL);  
	
	sleep(1);
    return 0;
}
           

       编译运行:

[email protected]:~/taoge/cpp$ g++ -g test.cpp -lpthread      
[email protected]:~/taoge/cpp$ valgrind --tool=memcheck --leak-check=yes --show-reachable=yes ./a.out  
==22531== Memcheck, a memory error detector
==22531== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==22531== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==22531== Command: ./a.out
==22531== 
==22531== 
==22531== HEAP SUMMARY:
==22531==     in use at exit: 272 bytes in 1 blocks
==22531==   total heap usage: 1 allocs, 0 frees, 272 bytes allocated
==22531== 
==22531== 272 bytes in 1 blocks are possibly lost in loss record 1 of 1
==22531==    at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22531==    by 0x40138A4: allocate_dtv (dl-tls.c:322)
==22531==    by 0x40138A4: _dl_allocate_tls (dl-tls.c:539)
==22531==    by 0x4E4226E: allocate_stack (allocatestack.c:588)
==22531==    by 0x4E4226E: pthread_create@@GLIBC_2.2.5 (pthread_create.c:539)
==22531==    by 0x40077C: main (test.cpp:15)
==22531== 
==22531== LEAK SUMMARY:
==22531==    definitely lost: 0 bytes in 0 blocks
==22531==    indirectly lost: 0 bytes in 0 blocks
==22531==      possibly lost: 272 bytes in 1 blocks
==22531==    still reachable: 0 bytes in 0 blocks
==22531==         suppressed: 0 bytes in 0 blocks
==22531== 
==22531== For counts of detected and suppressed errors, rerun with: -v
==22531== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
[email protected]:~/taoge/cpp$ 
           

        存在内存泄漏(possibly lost), 为什么呢? 因为线程默认是joinable的, 退出的时候, 需要pthread_join回收一下资源:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

void* threadFunc(void* p)  
{  
	char szTest[1024 * 32] = {0};
    return NULL;  
}  
 
int main(void)
{
	void *ret;
	
	pthread_t id;  
    pthread_create (&id, NULL, threadFunc, NULL);  
	
	pthread_join(id, &ret);
	
	sleep(1);
    return 0;
}
           

       编译运行:

[email protected]:~/taoge/cpp$ g++ -g test.cpp -lpthread                      [email protected]:~/taoge/cpp$ 
[email protected]:~/taoge/cpp$ valgrind --tool=memcheck --leak-check=yes --show-reachable=yes ./a.out  
==22710== Memcheck, a memory error detector
==22710== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==22710== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==22710== Command: ./a.out
==22710== 
==22710== 
==22710== HEAP SUMMARY:
==22710==     in use at exit: 0 bytes in 0 blocks
==22710==   total heap usage: 1 allocs, 1 frees, 272 bytes allocated
==22710== 
==22710== All heap blocks were freed -- no leaks are possible
==22710== 
==22710== For counts of detected and suppressed errors, rerun with: -v
==22710== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
[email protected]:~/taoge/cpp$ 
           

        可见,没有内存泄漏。

        还有一种思路, 让线程从默认的joinable变成detached,  如此一来, 线程在结束时, 自己就释放了资源:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

void* threadFunc(void* p)  
{  
	char szTest[1024 * 32] = {0};
    return NULL;  
}  
 
int main(void)
{
	size_t ui_stack_size = 0;
	pthread_attr_t attr;
	
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

	pthread_t id;  
    pthread_create (&id, &attr, threadFunc, NULL);  
	
	pthread_attr_destroy(&attr);
	
	sleep(1);
	
    return 0;
}
           

        编译运行:

[email protected]:~/taoge/cpp$ g++ -g test.cpp -lpthread                      [email protected]:~/taoge/cpp$ 
[email protected]:~/taoge/cpp$ valgrind --tool=memcheck --leak-check=yes --show-reachable=yes ./a.out  
==22900== Memcheck, a memory error detector
==22900== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==22900== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==22900== Command: ./a.out
==22900== 
==22900== 
==22900== HEAP SUMMARY:
==22900==     in use at exit: 0 bytes in 0 blocks
==22900==   total heap usage: 1 allocs, 1 frees, 272 bytes allocated
==22900== 
==22900== All heap blocks were freed -- no leaks are possible
==22900== 
==22900== For counts of detected and suppressed errors, rerun with: -v
==22900== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
[email protected]:~/taoge/cpp$ 
           

       没有内存泄漏了。

      两种方法, 各有千秋, 依据具体情况选择即可。

继续阅读