Я пробовал перегрузить глобальные операторы new
и delete
для своей программы:
Заголовок
void* operator new(std::size_t n);
void* operator new(std::size_t n, const std::nothrow_t&);
void operator delete(void* p);
Реализация
void* allocMemory(std::size_t n) {
MemoryAllocationRecord** pRecord = static_cast<MemoryAllocationRecord**>(
malloc(n + sizeof(MemoryAllocationRecord*)));
if (pRecord == nullptr) return nullptr;
void* retBlock = static_cast<void*>(pRecord+1);
*pRecord = nullptr;
//may set *pRecord to a legal pointer
return retBlock;
}
void* operator new(std::size_t n) {
void* ret = allocMemory(n);
if (ret == nullptr) throw std::bad_alloc();
return ret;
}
void* operator new(std::size_t n, const std::nothrow_t&) {
return allocMemory(n);
}
void operator delete(void* p) {
if (p == nullptr) return;
MemoryAllocationRecord** pRecord = static_cast<MemoryAllocationRecord**>(p) - 1;
if (*pRecord != nullptr){
//may use *pRecord as a legal pointer
}
return free(pRecord);
}
Когда я использую это в одном приложении (которое использует библиотеку Qt 5.11), оно работает без проблем. Но в другом приложении деструктор типа библиотеки (QList<QVariant>
) вызывает мой перегруженный delete
с памятью, которая выглядит следующим образом:
2a 38 02 00 fd fd fd fd*3c 28 5b 00 ...
*
отмечает пройденный указатель, поэтому pRecord == 0xfdfdfdfd0002382a
(а затем, естественно, вылетает). Достаточно ясно, что fdfdfdfd
- это заполнение памяти компилятором для обнаружения повреждений (я запускаю отладочную сборку), но я не понимаю, как и почему это происходит.
В случае, если что-то из этого имеет значение, компилятор - MSVC 2017, 64-битный двоичный, ОС - Windows 7, заголовок с перегрузками операторов включен в файл, в котором уничтожается QList<QVariant>
.
Другими словами, по крайней мере, вы не видите ничего, что могло бы быть ошибкой очень вероятно здесь, например, не перегружать void delete(void*, std::size_t)
или не проверять, что в каждом отдельном файле заголовок с перегрузкой оператора включен перед другими заголовками или что-то в этом роде?
Может также захотеть перегрузить new[]
и delete[]
. Какой-то (плохой) код вызывает delete
для материала, выделенного с помощью new[]
, который часто «просто работает» (пока он не работает).
Пытаясь найти ошибку в коде, легче позволить хорошему компилятору помочь, чем попросить читателя взять на себя роль компилятора. Я попытался кодировать ваш пример и столкнулся с двумя проблемами и получил предупреждения от компилятора. Однако у меня нет возможности узнать, есть ли у вас код, позволяющий обойти эти предупреждения. Я бы только догадывался, чтобы попросить вас объяснить мои ошибки компиляции, потому что мой код не совпадает с вашим. Похоже, это интересная проблема, с которой @SamVarshavchik, похоже, хочет помочь.
Возможно все, в том числе упомянутое «одно приложение» с ошибкой. Поэтому без минимальный воспроизводимый пример здесь больше ничего нельзя сказать.