Стратегия отладки памяти

Я ищу стратегию отладки памяти на С++. Я написал приложение, используя QT. Я использую Windows 7. Используемый компилятор - MinGW. В режиме отладки я иногда получал следующее отладочное сообщение: ОБНАРУЖЕНО ПОВРЕЖДЕНИЕ КУЧИ: после нормального блока (#...) в 0x...

Я предполагаю, что происходит следующее: Блок памяти освобождается с помощью удаления. После этого память используется.

В большинстве случаев это будет работать без проблем. Но иногда это приводит к сбою приложения. Мой вопрос в том, как отладить эту ошибку? Думаю о замене оператора new/delete.

Рассмотрим следующий оператор new/delete:

struct MemHandle
{
  void* ptr;
  size_t size;
}

void * operator new(std::size_t n) throw(std::bad_alloc)
{
  MemHandle Mem;
  void* p = malloc(n);
  Mem.ptr = p;
  Mem.size = n;
  //TODO: Store Mem
}
void operator delete(void * p) throw()
{
  MemHandle Mem = GetMemHandle(p);
  memset(p, 0, Mem.size);
  free(p);
}

В этом случае при повторном использовании памяти после удаления программа сразу вылетает. Это хорошая стратегия, или у вас есть вариант получше?


person MvHorssen    schedule 30.01.2016    source источник
comment
Возможный дубликат Как отлаживать ошибки повреждения кучи?   -  person user1641854    schedule 30.01.2016


Ответы (2)


То, чего вы пытаетесь достичь, - это ведение учета для каждого выделения памяти. Существуют доступные инструменты профилирования памяти (как коммерческие, так и с открытым исходным кодом), которые делают то же самое.
Valgrind — отличная программа, но она недоступна в Windows.
Purify — это коммерческий инструмент, который работает в Windows, и если вы ищете инструмент с открытым исходным кодом, то есть Dr Memory.
Вы можете ознакомиться с некоторыми другими инструментами здесь

person Amitoj    schedule 30.01.2016
comment
Я попробовал Dr Memory, но безуспешно. Программа постоянно вылетает. - person MvHorssen; 30.01.2016

Мой опыт говорит, что самым замечательным инструментом для отладки проблем с памятью являются дезинфицирующие средства памяти (и GCC, и LLVM их поддерживают, -fsanitize-memory). Он довольно быстрый, простой в использовании, и я был в ситуациях, когда valgrind ничего не видит, а дезинфицирующие средства видят. Дезинфицирующее средство памяти будет SIGABORT при обнаружении проблемы с памятью, поэтому трассировка стека будет немедленно у вас перед глазами. Некоторыми недостатками санайзеров являются повышенное использование кучи и немного сложный процесс сборки, но обычно это не проблема.

person user1641854    schedule 30.01.2016
comment
Поскольку GCC поддерживает его, он должен быть также доступен в MinGW, не так ли? - person MvHorssen; 30.01.2016
comment
Ну, должно быть. Но быстрый поиск показывает, что по крайней мере в середине 2015 года MinGW не поддерживал его. Но вы можете попробовать использовать clang. - person user1641854; 30.01.2016
comment
В любом случае, если ваше приложение является переносимым или вы можете перенести подозрительный фрагмент кода в Linux, вы можете использовать GCC или Clang с дезинфицирующими адресами оттуда. - person user1641854; 30.01.2016
comment
Это не вариант, приложение слишком велико, чтобы его можно было легко перенести в Linux. Я успешно перегрузил оператор new/delete. - person MvHorssen; 31.01.2016
comment
Программа может не вылететь в особом случае. Учтите, что ваше приложение считывает ранее освобожденную память, и значения 0 имеют для нее значение (например, целочисленное значение). Если распределитель памяти пользовательского пространства не вернул выделенную страницу, содержащую освобожденный кусок памяти, обратно в ОС - то вы не получите общую ошибку защиты механизма защиты страницы, и ваше приложение продолжит работу, так как ничего криминального не произошло. - person user1641854; 31.01.2016