Как правильно заменить глобальные операторы 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
}