C++内存泄露和内存管理

本文详细探讨了C++中的内存泄露问题,包括堆内存泄露和系统资源泄露,以及它们的危害。介绍了通过微软C运行时库的内存泄露检测方法,如_CrtDumpMemoryLeaks、_CrtMemCheckpoint和_CrtMemDifference等工具,以及如何通过_CrtSetBreakAlloc设置断点来定位内存泄露位置。此外,还提到了内存泄露的避免方法,如智能指针的使用和良好的编码习惯。最后,简要讨论了内存溢出的概念和类型,如堆栈溢出和缓冲区溢出,强调了内存越界可能导致的问题和排查原则。
摘要由CSDN通过智能技术生成

1   内存泄露

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

有两种类型的内存泄漏。

 

1.1 堆内存泄漏(Heap leak)

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



1.2系统资源泄露(Resource Leak)

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

下面简单介绍两种判断句柄泄露的方法:

1) 打开任务管理器:选择菜单:查看—选择列,勾上“句柄数“此时任务管理器中多了一列句柄数,如果你发现一个进程句柄数在不断增加,那么可能该进程就存在内存泄露了


2) 使用工具Process Explorer,该工具能够非常明了的看到进程所正在使用的内核对象,当存在句柄对象时,它能够协助你分析找到原因,选择View —> Lower Pane View —> DLLs (或Handles)


该程序在访问1.txt这个文件的时候,没有关闭句柄,导致文件打开时句柄不断增加。

 

2   内存泄露危害:

最直接的危害就是系统内存耗尽,系统死机。内存泄漏是最难发现的常见错误之一,因为除非用完内存或调用malloc失败,否则都不会导致任何问题。如果程序运行时间足够长,如后台进程运行在服务器上,只要服务器不宕机就一直运行,一个小小的失误也会对程序造成重大的影响,如造成某些关键服务失败。

 

3 内存泄露检测方法:

在Windows平台下,检测内存泄漏的方法主要有三两种,MS C-Runtime Library内建的检测功能;插件式的外部检测工具;性能检测工具分析系统内存泄露

 

3.1 MS C-Runtime Librarycrt(dbg.h中的api)

(内容来自http://www.cnblogs.com/skynet/archive/2011/02/20/1959162.html#

 

3.1.1 检测是否存在内存泄漏问题

Windows平台下面Visual Studio 调试器和 C 运行时 (CRT) 库为我们提供了检测和识别内存泄漏的有效方法,原理大致如下:内存分配要通过CRT在运行时实现,只要在分配内存和释放内存时分别做好记录,程序结束时对比分配内存和释放内存的记录就可以确定是不是有内存泄漏。在vs中启用内存检测的方法如下:

STEP1,在程序中包括以下语句:(#include 语句必须采用下文所示顺序。如果更改了顺序,所使用的函数可能无法正常工作。)

#define _CRTDBG_MAP_ALLOC

#include <stdlib.h>

#include <crtdbg.h>

通过包括 crtdbg.h,将malloc和free函数映射到它们的调试版本,即_malloc_dbg和_free_dbg,这两个函数将跟踪内存分配和释放。此映射只在调试版本(在其中定义了_DEBUG)中发生。 发布版本使用普通的malloc和free函数。

#define 语句将 CRT 堆函数的基版本映射到对应的“Debug”版本。 并非绝对需要该语句;但如果没有该语句,内存泄漏转储包含的有用信息将较少。

STEP2, 在添加了上述语句之后,可以通过在程序中包括以下语句(通常应恰好放在程序退出位置之前)来转储内存泄漏信息:

_CrtDumpMemoryLeaks();

此时,完整的代码如下:

#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);

}

 

int main(int argc,char** argv)

{

    char *str= NULL;

    GetMemory(str,100);

    cout<<"Memory leak test!"<<endl;

    _CrtDumpMemoryLeaks();

    return 0;

}

当在调试器下运行程序时,_CrtDumpMemoryLeaks将在“输出”窗口中显示内存泄漏信息。 内存泄漏信息如下所示:


如果没有使用 #define_CRTDBG_MAP_ALLOC 语句,内存泄漏转储将如下所示:


内存泄露报告说明:

1) 大括号内的127:内存分配编号

2)大括号后的normal block:块类型(普通、客户端或 CRT)

“普通块”是由程序分配的普通内存

“客户端块”是由 MFC 程序用于需要析构函数的对象的特殊类型内存块。 MFC new 操作根据正在创建的对象的需要创建普通块或客户端块。

“CRT 块”是由 CRT 库为自己使用而分配的内存块。 CRT 库处理这些块的释放,因此您不大可能在内存泄漏报告中看到这些块,除非出现严重错误(例如 CRT 库损坏)。

从不会在内存泄漏信息中看到下面两种块类型:

“可用块”是已释放的内存块。

“忽略块”是您已特别标记的块,因而不出现在内存泄漏报告中。

3) CD CD:十六进制形式的内存位置。

4) 定义了 _CRTDBG_MAP_ALLO

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值