Подтвердить что ты не робот

Простейший способ подсчета экземпляров объекта

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

atomic<int> cntMyObject;

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

Взгляните на этот. Ответьте на вопросы по С++, чтобы узнать, как это сделать и какие меры предосторожности вы должны предпринять.

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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

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

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

Ответ 6

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

Ответ 7

Мой подход, который выводит счетчик утечек на вывод Debug (через функцию 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>