博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
内存泄露的排查
阅读量:2229 次
发布时间:2019-05-09

本文共 2515 字,大约阅读时间需要 8 分钟。

内存泄露的排查

黄国强 2010-5-24
1 内存泄露的现象和危害
      在C++中,当我们用 new 分配了一段内存,而在用完了以后忘了用 delete 释放,这样内存泄露就产生了。
      内存泄露对于长期运行的程序 是致命的,它会导致系统可用内存越来越少,最终导致将程序崩溃。下面用具体的例子来说明内存泄露的产生,以及解决的方法。
2 例子工程的建立
      使用VC7.1(也就是VS2003),创建过程的设置如下:
      step1:新建项目,项目选 项是“Visual C++项目/win32/win32控制台项目”
      step2:在随后弹出的“应用程序设置”的“应用程序类型”中“选择控制 台应用程序”,并在“添加支持”中选择“MFC”。
3 内存泄露的代码示例1
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    int nRetCode = 0;
    // 初始化 MFC 并在失败时显示错误
    if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
    {
        // TODO: 更改错误代码以符合您的需要
        _tprintf(_T("致命错误: MFC 初始化失败/n"));
        nRetCode = 1;
    }
    else
    {
        // TODO: 在此处为应用程序的行为编写代码。
    }
    int * p = new int;        // 分配了大小为一个int的内存
    int * p2 = new int[8];     // 分配了一个int数组的内存
    return nRetCode;
}
选择Debug,运行这个程序。

在VC输出栏就会出现下面的提示,说明有内 存泄露存在。(当然这个例子是否有害,在此不讨论)

Detected memory leaks!
Dumping objects ->
d:/temp/meleak/meleak/meleak.cpp(34) : {120} normal block at 0x00346300, 32 bytes long.
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
d:/temp/meleak/meleak/meleak.cpp(33) : {119} normal block at 0x003462C0, 4 bytes long.
 Data: <    > CD CD CD CD
我们在VC输出栏中双击
“d:/temp/meleak/meleak/meleak.cpp(34) : {120} normal block at 0x00346300, 32 bytes long.”,VC就会自动定位到源码发生内存泄露的位置。(我曾经遇到过好几次,有人居然不知道这个功能。所以特别写下来,希望不是废话)
解决的方法就是分别写上如下两行代码即可。
    delete p;         // 释放一般指针
    delete[] p2;     // 释放数组
但是以上方法不好,下面推荐的是另外一种方法。代码如下:
std::auto_ptr<int> p3(new int);
std::vector<int> p4(8);
p =  p3.get();     // 这时候的p无需释放
p2 = &p4[0];     // 这时候的p2也无需释放
4 内存泄露的代码示例2
下 面是一个比较隐蔽的例子
class CBase
{
public:
    CBase(void){}
    ~CBase(void){}
};
class CDerive : public CBase
{
public:
    CDerive(const CString& strVal):m_strVal(strVal){}
    ~CDerive(void){}
private:
    CString m_strVal;
};
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    int nRetCode = 0;
    // 初始化 MFC 并在失败时显示错误
    if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
    {
        // TODO: 更改错误代码以符合您的需要
        _tprintf(_T("致命错误: MFC 初始化失败/n"));
        nRetCode = 1;
    }
    else
    {
        // TODO: 在此处为应用程序的行为编写代码。
    }
    std::auto_ptr<CBase> pBase(new CDerive("文本"));
    return nRetCode;
}
选择Debug,运行这个程序。
在VC输出栏就会出现下面的提 示,说明有内存泄露存在。
Detected memory leaks!
Dumping objects ->
{124} normal block at 0x00346390, 21 bytes long.
 Data: <  2|            > D8 BC 32 7C 04 00 00 00 04 00 00 00 01 00 00 00
Object dump complete.
上面的这段提示,并没有给出是哪行代码出了问题,这时我们可以用到下面的方法。
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    _CrtSetBreakAlloc(124); // 加入此行,124就是VC输出栏的{}中的数字
    ...
}
选择 Debug 运行这个程序。一旦分配到124这个内存,VC就会停下来,这样,我们就可以从调用堆栈中查出是哪一行导致内存泄露。
这个bug的原因是在 ~CBase(void){} 少了个 virtual。下面的是正确的写法。
class CBase
{
public:
    CBase(void){}
    virtual ~CBase(void){}
};   

转载地址:http://klefb.baihongyu.com/

你可能感兴趣的文章
探索Redis设计与实现10:Redis的事件驱动模型与命令执行过程
查看>>
分布式系统理论基础1: 一致性、2PC和3PC
查看>>
分布式系统理论基础2 :CAP
查看>>
分布式系统理论基础3: 时间、时钟和事件顺序
查看>>
分布式系统理论基础4:Paxos
查看>>
分布式系统理论基础5:选举、多数派和租约
查看>>
分布式系统理论基础6:Raft、Zab
查看>>
分布式系统理论进阶7:Paxos变种和优化
查看>>
分布式系统理论基础8:zookeeper分布式协调服务
查看>>
搞懂分布式技术1:分布式系统的一些基本概念
查看>>
搞懂分布式技术2:分布式一致性协议与Paxos,Raft算法
查看>>
搞懂分布式技术3:初探分布式协调服务zookeeper
查看>>
搞懂分布式技术4:ZAB协议概述与选主流程详解
查看>>
搞懂分布式技术5:Zookeeper的配置与集群管理实战
查看>>
搞懂分布式技术6:Zookeeper典型应用场景及实践
查看>>
搞懂分布式技术10:LVS实现负载均衡的原理与实践
查看>>
搞懂分布式技术11:分布式session解决方案与一致性hash
查看>>
搞懂分布式技术12:分布式ID生成方案
查看>>
搞懂分布式技术13:缓存的那些事
查看>>
搞懂分布式技术14:Spring Boot使用注解集成Redis缓存
查看>>