c++:一个辅助类让内存泄漏现原形!

如何判断内存有泄漏

内存分配和释放对应的操作是new、delete。如何判断内存是否释放干净?其实判断起来非常简单:一个独立的模块整个生存周期内new的个数和delete的个数相等。用伪代码标示如下:

复制代码
int newCount = 0;
int deleteCount = 0;

//new 操作时
new class();
newCount++;

//delete 操作时
delete* objPtr;
deleteCount++;

//模块结束时

if(newCount != deleteCount)
{
内存有泄漏
}
复制代码
如果对所有的new和delete操作,加上如上几行代码,就能发现是否有内存泄漏问题。如果采用上面方法解决问题,手段太low了。

我们的方法有如下特点:

1 使用起来超级简单,不增加开发难度。

2 发生内存泄漏时,能定位到具体是哪个类。

托管new delete 操作符

要跟踪所有的new、delete操作,最简单的办法就是托管new、delete。不直接调用系统的操作符,而是用我们自己写的函数处理。在我们的函数内部,则别有洞天; 对new和delete的跟踪和记录就为我所欲也。托管new和delete需用到模板函数,代码如下:

复制代码
class MemManage
{
//单实例模式
private:
static MemManage* _instance_ptr;
public:
static MemManage* instance()
{
if (_instance_ptr == nullptr)
{
_instance_ptr = new MemManage();
}
return _instance_ptr;
}

public:
MemManage();

//new操作 构造函数没有参数
template <typename  T>
T* New()
{
    ShowOperationMessage<T>(true);
    return new T();
};

//new操作 构造函数有1个参数
template <typename  T, typename TParam1>
T* New(TParam1 param)
{
    ShowOperationMessage<T>(true);
    return new T(param);
};

//new操作 构造函数有2个参数
template <typename  T, typename TParam1, typename TParam2>
T* New(TParam1 param1, TParam2 param2)
{
    ShowOperationMessage<T>(true);
    return new T(param1, param2);
};

//delete 操作
template <typename  T>
void  Delete(T t)
{
    if (t == nullptr)
        return;

    ShowOperationMessage<T>(false);
    delete t;
};

//记录new delete
template <typename  T>
void ShowOperationMessage(bool isNew)
{
    //操作符对应的类名称
    const type_info& nInfo = typeid(T);
    QString className = nInfo.name();

    if (isNew)
    {
        _newCount++;
    }
    else
    {
        _deleteCount++;
    }

    if (!_showDetailMessage)
    {
        return;
    }

    if (isNew)
    {
        qDebug() << "*New" << className << ":" << _newCount << ":" << _deleteCount;
    }
    else
    {
        qDebug() << "Delete" << className << ":" << _newCount << ":" << _deleteCount;
    }
}

}
复制代码
如何使用辅助类

使用起来很简单,示例代码如下:

复制代码
//*****new和delete使用伪代码

//new操作,需根据构造函数的参数个数调用对应的函数
//构造函数 没有参数
QFile* file = MemManage::instance()->New();

//构造函数 有1个参数
QFile* file = MemManage::instance()->New<QFile, QString>(“filename”);

//构造函数 有2个参数
QFile* file = MemManage::instance()->New<QFile, QString,bool>(“filename”,true);

//delete 只有一种形式
MemManage::instance()->Delete(file);
复制代码
一个模块调用周期结束 调用下列代码,查看是否有内存泄漏:

复制代码
void ShowNewDelete(bool isShowDetail)
{
int leftNew = _newCount - _deleteCount;
qDebug() << “***********************”;
qDebug() << “total New:” << _newCount << " Delete:" << _deleteCount << " leftNew:" << leftNew;
}

MemManage::instance()->ShowNewDelete(true);
//debug输出如下,如果leftNew为0,则没内存泄漏
total New : 166  Delete : 6  leftNew : 160

复制代码
进一步定位内存泄漏问题

通过判断new和delete的个数是否相等,只是知道了是否有内存泄漏;进一步定位问题,才能方便我们解决问题。如果能定位到操作哪一个类时,发生了内存泄漏,则问题范围就大大缩小。我们可以按类名,记录new和delete操作个数,c++获取类名函数如下:

const type_info &nInfo = typeid(T);
QString className = nInfo.name();
建立一个map表,记录类名对应的操作信息:

复制代码
//每个类 统计的信息
class MemObjInfo
{
public:
int NewCount = 0;
int DeletCount = 0;
QString ClassName;
};

//map对照表
QMap<QString, MemObjInfo*> _mapMemObjCount;

//按类名统计
void AddCount(QString& className, bool isNew)
{
QMap<QString, MemObjInfo*>::ConstIterator i = _mapMemObjCount.find(className);
if (i == _mapMemObjCount.constEnd())
{
MemObjInfo* info = new MemObjInfo();
info->ClassName = className;
if (isNew)
{
info->NewCount++;
}
else
{
info->DeletCount++;
}
_mapMemObjCount.insert(className, info);
}
else
{
MemObjInfo* info = i.value();
if (isNew)
{
info->NewCount++;
}
else
{
info->DeletCount++;
}
}
}
USB Microphone https://www.soft-voice.com/
Wooden Speakers https://www.zeshuiplatform.com/
亚马逊测评 www.yisuping.cn
深圳网站建设www.sz886.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值