Simplest way to count instances of an object

后端 未结 8 1904
时光取名叫无心
时光取名叫无心 2021-01-01 17:42

I would like to know the exact number of instances of certain objects allocated at certain point of execution. Mostly for hunting possible memory leaks(I mostly use RAII, al

相关标签:
8条回答
  • 2021-01-01 18:12

    Adding counters to individual classes was discussed in some of the answers. However, it requires to pick the classes to have counted and modify them in one way or the other. The assumption in the following is, you are adding such counters to find bugs where more objects of certain classes are kept alive than expected.

    To shortly recap some things mentioned already: For real memory leaks, certainly there is valgrind:memcheck and the leak sanitizers. However, for other scenarios without real leaks they do not help (uncleared vectors, map entries with keys never accessed, cycles of shared_ptrs, ...).

    But, since this was not mentioned: In the valgrind tool suite there is also massif, which can provide you with the information about all pieces of allocated memory and where they were allocated. However, let's assume that valgrind:massif is also not an option for you, and you truly want instance counts.

    For the purpose of occasional bug hunting - if you are open for some hackish solution and if the above options don't work - you might consider the following: Nowadays, many objects on the heap are effectively held by smart pointers. This could be the smart pointer classes from the standard library, or the smart pointer classes of the respective helper libraries you use. The trick is then the following (picking the shared_ptr as an example): You can get instance counters for many classes at once by patching the shared_ptr implementation, namely by adding instance counts to the shared_ptr class. Then, for some class Foo, the counter belonging to shared_ptr<Foo> will give you an indication of the number of instances of class Foo.

    Certainly, it is not quite as accurate as adding the counters to the respective classes directly (instances referenced only by raw pointers are not counted), but possibly it is accurate enough for your case. And, certainly, this is not about changing the smart pointer classes permanently - only during the bug hunting. At least, the smart pointer implementations are not too complex, so patching them is simple.

    0 讨论(0)
  • 2021-01-01 18:15

    Have a "counted object" class that does the proper reference counting in its constructor(s) and destructor, then derive your objects that you want to track from it. You can then use the curiously recurring template pattern to get distinct counts for any object types you wish to track.

    // 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>
    {};
    
    0 讨论(0)
  • 2021-01-01 18:16

    My approach, which outputs leakage count to Debug Output (via the DebugPrint function implemented in our code base, replace that call with your own...)

    #include <typeinfo> 
    #include <string.h>
    class CountedObjImpl
    {
    public:
            CountedObjImpl(const char* className) : mClassName(className) {}
            ~CountedObjImpl()
            {
                    DebugPrint(_T("**##** Leakage count for %hs: %Iu\n"), mClassName.c_str(), mInstanceCount);
            }
            size_t& GetCounter() 
            {
                    return mInstanceCount;
            }
    
    private:
            size_t mInstanceCount = 0;
            std::string mClassName;
    };
    
    template <class Obj>
    class CountedObj
    {
    public:
            CountedObj() { GetCounter()++; }
            CountedObj(const CountedObj& obj) { GetCounter()++; }
            ~CountedObj() { GetCounter()--; }
    
            static size_t OustandingObjects() { return GetCounter(); }
    
    private:
            size_t& GetCounter()
            {
                    static CountedObjImpl mCountedObjImpl(typeid(Obj).name());
                    return mCountedObjImpl.GetCounter();
            }
    };
    

    Example usage:

    class PostLoadInfoPostLoadCB : public PostLoadCallback, private CountedObj<PostLoadInfoPostLoadCB>
    
    0 讨论(0)
  • 2021-01-01 18:18

    you can apply this approach

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

    at DEBUG mode, invoking of ObjectCount::showCount() method will return count of object(s) created.

    0 讨论(0)
  • 2021-01-01 18:26

    Without knowing your code and your requirements, I see 2 reasonable options:

    a) Use boost::shared_ptr. It has the atomic reference counts you suggested built in and takes care of your memory management (so that you'd never actually care to look at the count). Its reference count is available through the use_count() member.

    b) If the implications of a), like dealing with pointers and having shared_ptrs everywhere, or possible performance overhead, are not acceptable for you, I'd suggest to simply use available tools for memory leak detection (e.g. Valgrind, see above) that'll report your loose objects at program exit. And there's no need to use intrusive helper classes for (anyway debug-only) tracking object counts, that just mess up your code, IMHO.

    0 讨论(0)
  • 2021-01-01 18:27

    We used to have the solution of a base class with internal counter and derive from it, but we changed it all into boost::shared_ptr, it keeps a reference counter and it cleans up memory for you. The boost smart pointer family is quite useful: boost smart pointers

    0 讨论(0)
提交回复
热议问题