Самый простой способ подсчета экземпляров объекта - PullRequest
15 голосов
/ 17 августа 2011

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

atomic<int> cntMyObject;

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

Ответы [ 7 ]

27 голосов
/ 17 августа 2011

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

// 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>
{};
9 голосов
/ 17 августа 2011

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

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

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

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

7 голосов
/ 26 августа 2011

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

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

    }
};

в режиме DEBUG, вызов метода ObjectCount::showCount() вернет количество созданных объектов.

3 голосов
/ 17 августа 2011

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

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

2 голосов
/ 26 августа 2011

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

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

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

1 голос
/ 21 ноября 2017

Мой подход, который выводит счетчик утечек в вывод отладки (с помощью функции 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>
1 голос
/ 23 августа 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...