关于C++中的内存泄露

1.c++内存泄漏的定义:

内存泄漏(memory leak)是指由于疏忽或错误造成了程序未能释放掉不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。

2.内存泄漏的后果:

最难捉摸也最难检测到的错误之一是内存泄漏,即未能正确释放以前分配的内存的 bug。 只发生一次的小的内存泄漏可能不会被注意,但泄漏大量内存的程序或泄漏日益增多的程序可能会表现出各种征兆:从性能降低到内存完全用尽。 更糟的是,泄漏的程序可能会用掉太多内存,导致另一个程序失败,而使用户无从查找问题的真正根源。 此外,即使无害的内存泄漏也可能会引发各种 问题,更有可能导致系统崩溃。

3.主要关注两种类型的内存泄漏:

(1)堆内存泄漏 (Heap leak)。对内存指的是程序运行中根据需要分配通过malloc,realloc ,new等从堆中分配的一块内存,再是完成后必须通过调用对应的 free或者delete 删掉。如果程序的设计的错误导致这部分内存没有被释放,那么此后这块内存将不会被使用,就会产生Heap Leak.

(2)系统资源泄露(Resource Leak).主要指程序使用系统分配的资源比如 Bitmap,handle ,SOCKET等没有使用相应的函数释放掉,导致系统资源的浪费,严重可导致系统效能降低,系统运行不稳定。

4.检测内存泄露的方法:

(1)调试运行DEBUG版程序,运用以下技术:CRT(C run-time libraries)(_CrtDumpMemoryLeaks())、运行时函数调用堆栈、内存泄漏时提示的内存分配序号(集成开发环境OUTPUT窗口),综合分析内存泄漏的原因,排除内存泄漏。

(2)运行的时候用valgrind跑,可以检查运行时候存在的内存泄漏。

参考资料:

C++怎么检测内存泄露,怎么定位内存泄露? (知乎)

C++不用工具,如何检测内存泄漏? (知乎)

下面这样就会发生内存泄露,需要free 或者 delete。

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <iostream>
using namespace std;

void GetMemory(char *p, int num)
{
	p = (char*)malloc(sizeof(char)* num);
	//free(p);
	//delete p;
}

int main(int argc, char** argv)
{
	char *str = NULL;
	GetMemory(str, 100);

	cout << "Memory leak test!" << endl;
	_CrtDumpMemoryLeaks(); //检测内存泄露
	return 0;
}

运行上面代码会出现检测信息(此时发生内存泄露):

Detected memory leaks!
Dumping objects ->
c:userslzyrapxdocumentsvisual studio 2013projects	est	est	est.cpp(9) : {145} normal block at 0x00D79F18, 100 bytes long.
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
Object dump complete.

5.预防内存泄露的方法:

解决内存泄漏最有效的办法就是使用智能指针(Smart Pointer)。使用智能指针就不用担心这个问题了,因为智能指针可以自动删除分配的内存。智能指针和普通指针类似,只是不需要手动释放指针,而是通过智能指针自己管理内存的释放,这样就不用担心内存泄漏的问题了。c++ 提供了auto_ptr、unique_ptr、shared_ptr和weak_ptr这几种智能指针(auto_ptr是C++98提供的解决方案,C+11已将将其摒弃,并提供了另外两种解决方案)。

6."智能指针"前置知识:

(1) shared_ptr是一个共享的智能指针:

shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。在最后一个shared_ptr析构的时候,内存才会被释放。

注意事项:

1.不要用一个原始指针初始化多个shared_ptr。

2.不要再函数实参中创建shared_ptr,在调用函数之前先定义以及初始化它。

3.不要将this指针作为shared_ptr返回出来。

4.要避免循环引用。

(2) unique_ptr 独占的智能指针:

<1>Unique_ptr 是一个独占的智能指针,他不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另外一个unique_ptr。

<2>unique_pt r不允许复制,但可以通过函数返回给其他的unique_ptr,还可以通过std::move来转移到其他的unique_ptr,这样它本身就不再拥有原来指针的所有权了。

<3>如果希望只有一个智能指针管理资源或管理数组就用unique_ptr,如果希望多个智能指针管理同一个资源就用shared_ptr。

(3) weak_ptr弱引用的智能指针:

弱引用的智能指针weak_ptr是用来监视shared_ptr的,不会使引用计数加一,它不管理shared_ptr内部的指针,主要是为了监视shared_ptr的生命周期,更像是shared_ptr的一个助手。

weak_ptr没有重载运算符*和->,因为它不共享指针,不能操作资源,主要是为了通过shared_ptr获得资源的监测权,它的构造不会增加引用计数,它的析构不会减少引用计数,纯粹只是作为一个旁观者来监视shared_ptr中关连的资源是否存在。

weak_ptr还可以用来返回this指针和解决循环引用的问题。

7.野指针

野指针:指向被释放的或者访问受限内存的指针。

造成野指针的原因:

1.指针变量没有被初始化(如果值不定,可以初始化为NULL)

2.指针被free或者delete后,没有设置为NULL, free和delete只是把指针所指向的内存给释放掉,并没有把指针本身干掉,此时指针指向的是“垃圾”内存。释放后的指针应该被置为NULL.

3.指针操作超越了变量的作用范围,比如返回指向栈内存的指针就是野指针。

8.参考资料:

C/C++内存泄漏及检测

C++中内存泄漏的几种情况

原文地址:https://www.cnblogs.com/LzyRapx/p/8679249.html