Самый простой способ подсчета экземпляров объекта

Я хотел бы знать точное количество экземпляров определенных объектов, выделенных в определенной точке выполнения. В основном для поиска возможных утечек памяти (я в основном использую RAII, почти не новый, но все же я мог забыть .clear () on vector перед добавлением новых элементов или чего-то подобного). ОФК я мог бы иметь

atomic<int> cntMyObject;

что я -- в деструкторе, ++ увеличение конструктора, конструктор cpy (надеюсь, я охватил все :)). Но это жесткое кодирование для каждого класса. И это не просто отключите его в режиме "выпуск". Итак, есть ли простой элегантный способ, который можно легко отключить для подсчета экземпляров объектов?

7 ответов


есть класс" подсчитанный объект", который выполняет правильный подсчет ссылок в его конструкторе(конструкторах) и деструкторе, а затем выводит ваши объекты, которые вы хотите отслеживать из него. Затем вы можете использовать любопытно повторяющийся шаблон, чтобы получить отдельные счетчики для любых типов объектов, которые вы хотите отслеживать.

// 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>
{};

лучше использовать профилирование памяти и инструменты обнаружения утечек, такие как Valgrind или Rational Purify.

Если вы не можете и хотите реализовать свой собственный механизм, затем,

вы должны перегрузить new и delete операторы для вашего класса, а затем реализуют диагностику памяти в них.

посмотреть этой C++ FAQ ответ, чтобы знать, как это сделать и какие меры предосторожности вы должны принять.


вы можете применить этот подход

#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 режим вызова ObjectCount::showCount() метод вернет количество созданных объектов.


Это своего рода рабочий пример чего-то подобного:http://www.almostinfinite.com/memtrack.html (Просто скопируйте код в конце страницы и поместите его в Memtrack.h, а затем запустите TrackListMemoryUsage () или одну из других функций, чтобы увидеть диагностику)

Он переопределяет оператор new и делает некоторые тайные макросы, чтобы сделать его "штампом" каждого выделения с информацией, которая позволяет подсчитать, сколько экземпляров объекта и сколько памяти они usingusing. Однако это не идеально, макросы, которые они используют, ломаются при определенных условиях. Если вы решите попробовать это, обязательно включите его после любых стандартных заголовков.


не зная ваш код и ваши требования, я вижу 2 разумных варианта:

a) использовать boost::shared_ptr. Он имеет атомарные отсчеты ссылок, которые вы предложили встроить, и заботится о вашем управлении памятью (так что вы никогда не захотите взглянуть на счетчик). Его счетчик ссылок доступен через use_count() член.

b) если последствия a), как иметь дело с указателями и иметь shared_ptrs везде, или возможные накладные расходы, не являются приемлемыми для вас я бы предложил просто использовать доступные инструменты для обнаружения утечки памяти (например,отчет, см. выше), который сообщит о ваших свободных объектах при выходе из программы. И нет необходимости использовать навязчивые вспомогательные классы для (Во всяком случае, только для отладки) подсчета объектов отслеживания, которые просто испортят ваш код, IMHO.


раньше у нас было решение базового класса с внутренним счетчиком и производным от него, но мы изменили его на boost::shared_ptr, он сохраняет ссылочный счетчик и очищает память для вас. Семейство интеллектуальных указателей boost довольно полезно: повысить смарт-указатели


мой подход, который выводит количество утечек для отладки вывода(через функцию DebugPrint, реализованную в нашей базе кода, замените этот вызов своим собственным...)

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

пример использования:

class PostLoadInfoPostLoadCB : public PostLoadCallback, private CountedObj<PostLoadInfoPostLoadCB>