C++ 计算对象实例数的最简单方法

C++ 计算对象实例数的最简单方法,c++,refcounting,C++,Refcounting,我想知道在特定执行点分配的特定对象的实例的确切数量。主要用于查找可能的内存泄漏(我主要使用RAII,几乎没有新的,但在添加新元素或类似内容之前,我仍然可以忘记向量上的.clear()。我可以有一个 atomic<int> cntMyObject; 原子对象; 在析构函数中,++增加构造函数,cpy构造函数(我希望我涵盖了所有内容:)。 但这是每个类的硬编码。在“释放”模式下禁用它并不简单。 那么,有什么简单而优雅的方法可以轻松地禁用以计算对象实例吗?最好使用内存分析和泄漏检测工具

我想知道在特定执行点分配的特定对象的实例的确切数量。主要用于查找可能的内存泄漏(我主要使用RAII,几乎没有新的,但在添加新元素或类似内容之前,我仍然可以忘记向量上的.clear()。我可以有一个

atomic<int> cntMyObject;
原子对象;
在析构函数中,++增加构造函数,cpy构造函数(我希望我涵盖了所有内容:)。 但这是每个类的硬编码。在“释放”模式下禁用它并不简单。
那么,有什么简单而优雅的方法可以轻松地禁用以计算对象实例吗?

最好使用内存分析和泄漏检测工具,如Valgrind或Rational Purify

如果你不能并且想实现你自己的机制

您应该为您的类重载
new
delete
操作符,然后在其中实现内存诊断


查看<强> >强> C++ FAQ答案,知道如何做,注意什么。

< P>这是一个类似的例子:(只需复制页面末尾的代码并将其放在MeMtRe.h中,然后运行TrrkListMeMyLyAuthage(或)或其他函数中的一个来查看诊断)

它覆盖操作符new,并执行一些神秘的宏操作,使其在每个分配上“标记”信息,以便计算对象的实例数和使用的内存量。但这并不完美,它们使用的宏在某些条件下会崩溃。如果您决定尝试此方法,请确保将其包含在任何标准头之后。

拥有一个“counted object”类,该类在其构造函数和析构函数中进行适当的引用计数,然后从中派生您要跟踪的对象。然后,您可以使用奇怪的循环模板模式来获取要跟踪的任何对象类型的不同计数

// warning: pseudo code

template <class Obj>
class CountedObj
{
public:
   CountedObj() {++total_;}
   CountedObj(const CountedObj& obj) {if(this != &obj) ++total_;}
   ~CountedObj() {--total_;}

   static size_t OustandingObjects() {return total_;}

private:
   static size_t total_;
};

class MyClass : private CountedObj<MyClass>
{};
//警告:伪代码
模板
类CountedObj
{
公众:
CountedObj(){++total}
CountedObj(const CountedObj&obj){if(this!=&obj)++total}
~CountedObj(){--total;}
静态大小\u t OustandingObjects(){return total\u;}
私人:
静态尺寸(总尺寸);
};
类别MyClass:私有CountedObj
{};

我们以前使用带有内部计数器的基类解决方案并从中派生,但我们将其全部更改为boost::shared_ptr,它保留一个引用计数器并为您清理内存。boost智能指针系列非常有用:

您可以采用这种方法

#ifdef DEBUG

class ObjectCount {
    static int count;
  protected:
    ObjectCount() {
        count++;
    }
  public:
    void static showCount() {
        cout << count;
    }
};

int ObjectCount::count = 0;


class Employee : public ObjectCount {
#else
class Employee {
#endif
  public:
    Employee(){}
    Employee(const Employee & emp) {

    }
};
#ifdef调试
类对象计数{
静态整数计数;
受保护的:
ObjectCount(){
计数++;
}
公众:
void static showCount(){

在不了解您的代码和需求的情况下,我看到了两个合理的选择:

a) 使用
boost::shared_ptr
。它内置了您建议的原子引用计数,并负责您的内存管理(这样您就不会真正关心计数)。它的引用计数可通过
Use_count()
成员获得


b) 如果a)的含义(如处理指针和在任何地方共享
或可能的性能开销)对您来说都是不可接受的,我建议您只使用可用的工具进行内存泄漏检测(例如,Valgrind,见上文)这将在程序退出时报告您的松散对象。而且无需使用侵入式帮助器类(无论如何,仅用于调试)跟踪对象计数,这只会弄乱您的代码,IMHO。

我的方法,它将泄漏计数输出到调试输出(通过我们代码库中实现的DebugPrint函数,用您自己的调用替换该调用…)

#包括
#包括
类CountedObjImpl
{
公众:
CountedObjImpl(const char*className):mClassName(className){}
~CountedObjImpl()
{
DebugPrint(_T(“%hs的泄漏计数:%Iu\n”)、mClassName.c_str()、mInstanceCount);
}
大小\u t&GetCounter()
{
返回mInstanceCount;
}
私人:
大小_t mInstanceCount=0;
std::字符串mClassName;
};
模板
类CountedObj
{
公众:
CountedObj(){GetCounter()++;}
CountedObj(const CountedObj&obj){GetCounter()++;}
~CountedObj(){GetCounter()--;}
静态大小\u t OutstandingObjects(){return GetCounter();}
私人:
大小\u t&GetCounter()
{
静态CountedObjImpl mCountedObjImpl(typeid(Obj.name());
返回mCountedObjImpl.GetCounter();
}
};
用法示例:

class PostLoadInfoPostLoadCB : public PostLoadCallback, private CountedObj<PostLoadInfoPostLoadCB>
class PostLoadInfoPostLoadCB:public PostLoadCallback,private CountedObj

在一些答案中讨论了向单个类添加计数器。但是,需要选择要计数的类,并以某种方式对其进行修改。下面的假设是,添加此类计数器是为了发现某些类的更多对象保持活动状态的错误

简要回顾一下已经提到的一些事情:对于真正的内存泄漏,当然有valgrind:memcheck和泄漏清理器。但是,对于没有真正泄漏的其他场景,它们没有帮助(未清除的向量、从未访问过密钥的映射项、共享的线程循环等等)

但是,由于没有提到这一点:在valgrind工具套件中还有massif,它可以为您提供有关所有已分配内存的信息以及它们的分配位置。但是,让我们假设valgrind:massif也不是您的选项,您确实需要实例计数

用于偶尔的bug搜索——如果您对一些哈希解决方案开放,如果上述选项不起作用,您可能会考虑如下:现在堆上的许多对象都被智能指针有效地保存。这可能是智能指针类F

class PostLoadInfoPostLoadCB : public PostLoadCallback, private CountedObj<PostLoadInfoPostLoadCB>