Linux下通过valgrind定位程序内存问题

目录

内存泄露

重复释放

错误释放

相关资料


内存泄露

示例代码

// MemoryLeak.cpp : 定义控制台应用程序的入口点。
//

#include 
#include 

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 
#include 

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 
#include 

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, std::allocator >::_M_construct(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官方网站

 

Linux下通过valgrind定位程序内存问题_第1张图片 扫描二维码,关注“清远的梦呓”公众号,发现更多好文

 

你可能感兴趣的:(C++,Linux)