用valgrind檢測內存泄露的時候,發現一個問題,就是程序總會報一個泄露點
1 blocks are still reachable
查了程序發現並沒有泄露,最後百度才知道我對內存泄露的知識理解並不全面
以前我的理解是,只要分配的內存但是沒釋放就會導致內存泄露
但是這養理解是不全面的。只要分配了內存,如果它的指針沒有丟失,那麼就不算是泄露
所以來說,static的指針或者全局指針,如果沒有釋放它,那也算是not-freed blocks,也就是reachable的,但是現代的OS會得到這些指針並去釋放它
下面內容摘抄於https://bbs.csdn.net/topics/60443491 @天笑2001
- 使用全局指針或靜態指針:
int main()
{
static int *pi; // use static pointer: not a real memory leak!!!
pi = new int;
return 0;
}
使用valgrind檢查:
valgrind --leak-check=yes --show-reachable=yes -q ./memtest
==13782== searching for pointers to 1 not-freed blocks.
==13782== checked 4484352 bytes.
==13782==
==13782== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
==13782== at 0xB74D27AB: __builtin_new (vg_replace_malloc.c:172)
==13782== by 0xB74D2802: operator new(unsigned) (vg_replace_malloc.c:185)
==13782== by 0x8048491: main (in /home/prog/valgrind/memtest)
==13782== by 0xB71C4BA6: __libc_start_main (in /lib/libc-2.3.2.so)
==13782==
==13782== LEAK SUMMARY:
==13782== definitely lost: 4 bytes in 1 blocks.
==13782== possibly lost: 0 bytes in 0 blocks.
==13782== still reachable: 0 bytes in 0 blocks.
==13782== suppressed: 0 bytes in 0 blocks.
==13782==
報告說有一個"not-freed block",但這個block是reachable的,所以它不算是真正的memory leak.
- 如果使用的是局部指針:
int main()
{
int *pi; // use local pointer: real memory leak!!!
pi = new int[100];
return 0;
}
==13782== searching for pointers to 1 not-freed blocks.
==13782== checked 4484352 bytes.
==13782==
==13782== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
==13782== at 0xB74D27AB: __builtin_new (vg_replace_malloc.c:172)
==13782== by 0xB74D2802: operator new(unsigned) (vg_replace_malloc.c:185)
==13782== by 0x8048491: main (in /home/prog/valgrind/memtest)
==13782== by 0xB71C4BA6: __libc_start_main (in /lib/libc-2.3.2.so)
==13782==
==13782== LEAK SUMMARY:
==13782== definitely lost: 4 bytes in 1 blocks.
==13782== possibly lost: 0 bytes in 0 blocks.
==13782== still reachable: 0 bytes in 0 blocks.
==13782== suppressed: 0 bytes in 0 blocks.
==13782==
報告說是"definitely lost",這纔是真正的memory leak!
2 當然,我們一般情況下是不會分配內存而不釋放的. 它的典型應用便是著名的memory pool . 其要領是爲了提高內存管理的效率,針對特殊需要(如要分配的內存是等大的並且很小)去重載new,delete操作符. 它會避免每次申請很小的內存,而是一下子得到很大的一塊,再自己去定義和使用.(出於效率的考慮,它最後並不釋放) 我花了一下午時間分析的我用的SGI STL的內存分配源碼(我是在LINUX下使用g++的), 下面一段是在/usr/include/c++/3.2.3/bits/stl_alloc.h中找到的STL源碼:
template <bool __threads, int __inst> class __default_alloc_template
{
private:
enum {_ALIGN = 8};
enum {_MAX_BYTES = 128};
enum {_NFREELISTS = _MAX_BYTES / _ALIGN};
union _Obj
{
union _Obj * _M_free_list_link;
char _M_client_data[1]; // The client sees this.
};
static _Obj
* volatile _S_free_list[_NFREELISTS]; // Chunk allocation state.
static char * _S_start_free;
static size_t _S_heap_size;
static _STL_mutex_lock _S_node_allocator_lock;
....
}
可以看到,在關鍵的數據結構上,它使用了靜態的指針,並且定義了一些常量來控制內存塊的大小等.
3 對於這種技術是不是"隱式的內存泄漏" , 我認爲不是. 隱式的內存泄漏指分配內存後,雖然也釋放,但沒有及時釋放,導致內存消耗無法及時回收.在服務器編程時特別忌諱. 一般說來, 內存池的大小是可控, 不會一直增長下去. 從應用的層面上來說,它也是"釋放"了內存了的.