Как правильно заменить глобальные операторы new & delete
Прежде всего, было по крайней мере 4-5 тем с аналогичной темой на SO. Я читал каждый из них, и я не чувствую, что они действительно помогают мне в этой конкретной проблеме. Если кто-то найдет дублирующий вопрос, я приношу свои извинения. Я сделал свою долю поиска, прежде чем я разместил это, так как это кажется очень распространенным вопросом.
Я использую Visual Studio.NET 2003 в Windows 7.
У меня есть свои собственные перегрузки new/delete, которые указывают на мои собственные пользовательские вызовы malloc() и free() для диагностики. Мои новые/удаленные перегрузки находятся в файле заголовка, который я включил в несколько файлов.
Проблема в том, что база кода - это в значительной степени спагетти, и нет простого способа убедиться, что эти перегрузки используются всеми. В него входят сторонние библиотеки, которые имеют черный ящик. Мы также используем STL всюду.
В моих тестах я обнаружил, что STL по-прежнему смешивает вызовы со своим собственным новым/удаленным и стандартными вызовами new/delete MSVC.
Кажется нереальным включить мой заголовочный файл в тысячи других файлов, которые просто затянутся слишком долго. Может ли кто-нибудь предложить некоторые советы о том, как правильно и эффективно перегружать новые/удалить глобально, чтобы все использовало мой пользовательский менеджер памяти?
Ответы
Ответ 1
Это не так, как это работает. Вы заменяете два оператора, и это делается во время соединения. Все, что вам нужно сделать, это написать один TU, который определяет этих операторов и связывает их с миксами. Никто еще не должен знать об этом:
// optional_ops.cpp
void * operator new(std::size_t n) throw(std::bad_alloc)
{
//...
}
void operator delete(void * p) throw()
{
//...
}
В принципе, нет необходимости в каких-либо заголовочных файлах для объявления этих функций (operator new
, operator delete
), так как объявления этих двух функций уже жестко закодированы на языке, если хотите. Однако имена std
, std::bad_alloc
и std::size_t
не предопределены, поэтому вы, вероятно, захотите включить <new>
или какой-либо другой заголовок для предоставления этих имен.
В С++ 11 и далее вы можете использовать decltype(sizeof(0))
чтобы получить размер первого параметра таким образом, чтобы он не требовал какой-либо библиотеки. С++ 11 также имеет более простую модель исключения без спецификаций динамических исключений (которые были окончательно удалены из языка полностью на С++ 17).
void * operator new(decltype(sizeof(0)) n) noexcept(false)
{
//...
}
Ответ 2
Также добавьте следующие строки:
void *operator new[](std::size_t s) throw(std::bad_alloc)
{
// TODO: implement
return NULL;
}
void operator delete[](void *p) throw()
{
// TODO: implement
}