Современный C ++ затрудняет поиск утечек памяти - PullRequest
2 голосов
/ 30 октября 2019

Как вы должны тестировать современный C ++ на предмет утечек памяти?

Примеры юнит-тестов обычно выглядят так:

TestCase {
  Instantiate testObject
  testObject->AllocateSomeResources
  testObject->PerformATest
  testObject->DeallocateResources
  Destroy testObject
}

Мы используем valgrind для обнаружения утечек памяти. Это очень эффективно, если распределение ресурсов выполняется с new и delete, но когда ресурсы хранятся в виде интеллектуальных указателей внутри стандартных контейнеров, автоматическая очистка при уничтожении testObject не позволяет нам обнаруживать ошибки.

Когда система работает. Контейнеры ресурсов могут расти со временем из-за неправильной процедуры освобождения. Было бы тривиально выяснить, было ли выделение выполнено с new и delete.

Существуют ли какие-либо методы, которые исправят этот аспект современного C ++?

Идеи:

  • Сделать все деструкторы проверенными на выделенные ресурсы. Это немного повлияет на базу производственного кода.
  • Создание более отдельных и проверяемых процедур выделения и освобождения. Конечно, но так как мы получили это «бесплатно» с более традиционным C ++, я все же хотел бы найти альтернативы.

Очевидно, я вижу преимущество в стандартных контейнерах и умных указателях, извините зазаголовок наживки

Редактировать

Пример:

class A {
  int* resource;
  public:
    void allocate(){ resource = new int; }
    void deallocate(){ /*delete resouce;*/ }
};

class B {
  std::unique_ptr<int> resource;
  public:
    void allocate(){ resource = std::make_unique<int>(); }
    void deallocate(){ /*resource.reset();*/ }
};

И класс A, и B имеют один и тот же недостаток. Ошибка в функции deallocate заставляет их удерживать память, в которой они не нуждаются после вызова deallocate. С классом А это «фактическая утечка» и ее тривиально обнаружить, например, с помощью Valgrind в модульном тесте. Для класса B я могу только обнаружить недостаток в модульном тесте, выставив частный ресурс как публичный, что я не хочу делать. Этот вопрос не о Valgrind, а о том, существуют ли шаблоны, которые помогут мне получить продукт того же качества, который я достиг бы с Valgrind и классом A, но использующие стандартные контейнеры и умные указатели для хранения моих личных ресурсов.

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

1 Ответ

0 голосов
/ 30 октября 2019

Вы также можете тестировать отдельные методы Instantiate в своих юнит-тестах, а не тестировать все методы одновременно. Запустите каждый тест самостоятельно. Затем вы сможете найти утечки в каждом из отдельных методов.

Сделайте все деструкторы проверенными на выделенные ресурсы. Это немного повлияет на базу производственного кода. Ваши деструкторы будут вызываться всякий раз, когда вызывается delete или объект выходит из области видимости. Кажется, нет необходимости явно их проверять.

...