Linux下通過valgrind定位程序內存問題

目錄

內存泄露

重複釋放

錯誤釋放

相關資料


內存泄露

示例代碼

// MemoryLeak.cpp : 定義控制檯應用程序的入口點。
//

#include <stdlib.h>
#include <string>

char* AllocateMemory(size_t nSize)
{
	return new char[nSize];
}

int main()
{
	size_t nSize = 16;
	char* pszData = AllocateMemory(nSize);
	
	// do something	

	return 0;
}

編譯:g++ -Wall -g  MemoryLeak.cpp -o MemoryLeak

執行:valgrind --log-file=MemoryLeak.log --tool=memcheck --leak-check=full -v  ./MemoryLeak

MemoryLeak.log內容如下:

==14736== Memcheck, a memory error detector

==14736== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.

==14736== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info

==14736== Command: ./MemoryLeak

==14736== Parent PID: 3836

==14736==

==14736==

==14736== HEAP SUMMARY:

==14736==     in use at exit: 16 bytes in 1 blocks

==14736==   total heap usage: 2 allocs, 1 frees, 72,720 bytes allocated

==14736==

==14736== 16 bytes in 1 blocks are definitely lost in loss record 1 of 1

==14736==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==14736==    by 0x108691: AllocateMemory(unsigned long) (MemoryLeak.cpp:9)

==14736==    by 0x1086AF: main (MemoryLeak.cpp:15)

==14736==

==14736== LEAK SUMMARY:

==14736==    definitely lost: 16 bytes in 1 blocks

==14736==    indirectly lost: 0 bytes in 0 blocks

==14736==      possibly lost: 0 bytes in 0 blocks

==14736==    still reachable: 0 bytes in 0 blocks

==14736==         suppressed: 0 bytes in 0 blocks

==14736==

==14736== For counts of detected and suppressed errors, rerun with: -v

==14736== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

由於申請的16字節的內存沒有釋放,因此被檢測出16字節的泄露。 

重複釋放

示例代碼

// MemoryDoubleFree.cpp : 定義控制檯應用程序的入口點。
//

#include <stdlib.h>
#include <string>

char* AllocateMemory(size_t nSize)
{
	return new char[nSize];
}

void FreeMemory(char* pData)
{
	if (!pData)
	{
		return;
	}

	delete[] pData;
	pData = NULL;
}

int main()
{
	size_t nSize = 16;
	char* pszData = AllocateMemory(nSize);

	// do something	
	FreeMemory(pszData);
	FreeMemory(pszData);

	return 0;
}

編譯:g++ -Wall -g  MemoryDoubleFree.cpp -o MemoryDoubleFree

執行:valgrind --log-file= MemoryDoubleFree.log --tool=memcheck --leak-check=full ./ MemoryDoubleFree

MemoryDoubleFree.log內容如下: 

==15027== Memcheck, a memory error detector

==15027== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.

==15027== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info

==15027== Command: ./MemoryDoubleFree

==15027== Parent PID: 3836

==15027==

==15027== Invalid free() / delete / delete[] / realloc()

==15027==    at 0x4C3173B: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==15027==    by 0x108709: FreeMemory(char*) (MemoryDoubleFree.cpp:19)

==15027==    by 0x10874E: main (MemoryDoubleFree.cpp:30)

==15027==  Address 0x5b7dc80 is 0 bytes inside a block of size 16 free'd

==15027==    at 0x4C3173B: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==15027==    by 0x108709: FreeMemory(char*) (MemoryDoubleFree.cpp:19)

==15027==    by 0x108742: main (MemoryDoubleFree.cpp:29)

==15027==  Block was alloc'd at

==15027==    at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==15027==    by 0x1086E1: AllocateMemory(unsigned long) (MemoryDoubleFree.cpp:9)

==15027==    by 0x108732: main (MemoryDoubleFree.cpp:26)

==15027==

==15027==

==15027== HEAP SUMMARY:

==15027==     in use at exit: 0 bytes in 0 blocks

==15027==   total heap usage: 2 allocs, 3 frees, 72,720 bytes allocated

==15027==

==15027== All heap blocks were freed -- no leaks are possible

==15027==

==15027== For counts of detected and suppressed errors, rerun with: -v

==15027== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

申請的16字節的內存被釋放了兩次,屬於重複釋放。此種情況,不同編譯器編譯出的可執行程序的現象也不同,同時,也和內存的使用與回收情況有關。有的直接奔潰,有的可以暫時正常運行。 

錯誤釋放

示例代碼

// MemoryCheck.cpp : 定義控制檯應用程序的入口點。
//

#include <stdlib.h>
#include <string>

char* Serialize(size_t& nSize)
{
	std::string strData = "This is a MemCheck Programm With Valgrind";
	nSize = strData.size();
	return (char*)strData.c_str();
}


int main()
{
	size_t nSize = 0;
	char* pszData = Serialize(nSize);
	
	// do something

	delete[] pszData;
	pszData = NULL;

    return 0;
}

編譯運行:g++ -Wall -g  MemoryCheck.cpp -o MemoryCheck

執行:valgrind --log-file= MemoryCheck.log --tool=memcheck --leak-check=full ./MemoryCheck

MemoryCheck.log內容如下:

==15124== Memcheck, a memory error detector

==15124== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.

==15124== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info

==15124== Command: ./MemoryCheck

==15124== Parent PID: 3836

==15124==

==15124== Invalid free() / delete / delete[] / realloc()

==15124==    at 0x4C3173B: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==15124==    by 0x108B81: main (MemoryCheck.cpp:22)

==15124==  Address 0x5b7dc80 is 0 bytes inside a block of size 42 free'd

==15124==    at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==15124==    by 0x108B05: Serialize(unsigned long&) (MemoryCheck.cpp:9)

==15124==    by 0x108B6A: main (MemoryCheck.cpp:18)

==15124==  Block was alloc'd at

==15124==    at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==15124==    by 0x4F633AC: void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*>(char const*, char const*, std::forward_iterator_tag) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)

==15124==    by 0x108AC8: Serialize(unsigned long&) (MemoryCheck.cpp:9)

==15124==    by 0x108B6A: main (MemoryCheck.cpp:18)

==15124==

==15124==

==15124== HEAP SUMMARY:

==15124==     in use at exit: 0 bytes in 0 blocks

==15124==   total heap usage: 2 allocs, 3 frees, 72,746 bytes allocated

==15124==

==15124== All heap blocks were freed -- no leaks are possible

==15124==

==15124== For counts of detected and suppressed errors, rerun with: -v

==15124== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

由於strData的內存已經釋放(生命週期在Serialize函數),隨後通過delete[] 釋放已經釋放的資源,因此報錯。但是,程序表現可能很正常的退出,這個和編譯器有關,不同編譯器有不同表現,同時,也和內存的使用與回收情況有關。 

相關資料

valgrind官方網站

 

掃描二維碼,關注“清遠的夢囈”公衆號,發現更多好文

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章