valgrind的安装和调试很简单, 之前博文多次介绍(如果是ubuntu, 直接apt安装更简单, 一条命令搞定)。 最近遇到一个让人颇为难解的内存泄漏问题, 下面我们来抽取核心逻辑, 简单来说下:
先看看这段程序:
#include
#include
#include
#include
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;
}
编译运行:
ubuntu@VM-0-15-ubuntu:~/taoge/cpp$ g++ -g test.cpp -lpthread
ubuntu@VM-0-15-ubuntu:~/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)
ubuntu@VM-0-15-ubuntu:~/taoge/cpp$
存在内存泄漏(possibly lost), 为什么呢? 因为线程默认是joinable的, 退出的时候, 需要pthread_join回收一下资源:
#include
#include
#include
#include
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;
}
编译运行:
ubuntu@VM-0-15-ubuntu:~/taoge/cpp$ g++ -g test.cpp -lpthread ubuntu@VM-0-15-ubuntu:~/taoge/cpp$
ubuntu@VM-0-15-ubuntu:~/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)
ubuntu@VM-0-15-ubuntu:~/taoge/cpp$
可见,没有内存泄漏。
还有一种思路, 让线程从默认的joinable变成detached, 如此一来, 线程在结束时, 自己就释放了资源:
#include
#include
#include
#include
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;
}
编译运行:
ubuntu@VM-0-15-ubuntu:~/taoge/cpp$ g++ -g test.cpp -lpthread ubuntu@VM-0-15-ubuntu:~/taoge/cpp$
ubuntu@VM-0-15-ubuntu:~/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)
ubuntu@VM-0-15-ubuntu:~/taoge/cpp$
没有内存泄漏了。
两种方法, 各有千秋, 依据具体情况选择即可。