Предыдущий заголовок: "Должен ли я заменять глобальные операторы new и delete, чтобы изменить стратегию распределения памяти в стороннем коде?"
Рассказ: Нам нужно заменить технологию выделения памяти в сторонней библиотеке, не изменяя ее исходный код.
Длинная история:
Рассмотрим приложение с привязкой к памяти, которое делает огромные динамические распределения (возможно, почти все доступную системную память). Мы используем специализированные распределители и используем их везде (shared_ptr
, контейнеры и т.д.). У нас есть полный контроль и власть над каждым байтом памяти, выделенным в нашем приложении.
Кроме того, нам нужно связать с сторонней вспомогательной библиотекой. Этот противный парень делает выделение стандартным образом, используя операторы по умолчанию new
, new[]
, delete
и delete[]
или malloc
или что-то еще нестандартное (пусть обобщают и говорят, что мы не знаем, как эта библиотека управляет распределением кучи).
Если эта вспомогательная библиотека делает выделение достаточно большим, мы можем получить жесткие диски, фрагментацию памяти и проблемы с выравниванием, вне памяти bad_alloc
и всевозможные проблемы.
Мы не можем (или не хотим) изменять исходный код библиотеки.
Первая попытка:
У нас никогда не было таких нечестивых "хаков" в сборках релизов. Первый тест с переопределяющим оператором new
работает отлично, за исключением того, что:
- мы не знаем, что ждет нас в будущем (и это ужасно)
- наши пользователи (и даже наши распределители) теперь должны выделять то же самое, что мы делаем
Вопросы:
- Есть ли способы перехвата этих распределений без перегрузки глобальных операторов? (локальные перехватчики только для lib?)
- ... и если мы не знаем, что именно он использует:
malloc
илиnew
? -
Является ли этот список сигнатур законченным? (и нет других вещей, которые мы должны реализовать):
void* operator new (std::size_t size) throw (std::bad_alloc); void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) throw(); void* operator new (std::size_t size, void* ptr) throw(); void* operator new[] (std::size_t size) throw (std::bad_alloc); void* operator new[] (std::size_t size, const std::nothrow_t& nothrow_value) throw(); void* operator new[] (std::size_t size, void* ptr) throw(); void operator delete (void* ptr) throw(); void operator delete (void* ptr, const std::nothrow_t& nothrow_constant) throw(); void operator delete (void* ptr, void* voidptr2) throw(); void operator delete[] (void* ptr) throw(); void operator delete[] (void* ptr, const std::nothrow_t& nothrow_constant) throw(); void operator delete[] (void* ptr, void* voidptr2) throw();
-
Что-то другое, если эта библиотека динамична?
Изменить # 1
Кросс-платформенное решение предпочтительнее, если это возможно (похоже, не очень возможно). Если нет, наши основные платформы:
- Windows x86/x64 (msvc 10)
- Linux x86/x64 (gcc 4.6)
Изменить # 2
Прошло почти 2 года, несколько версий ОС и компиляторов эволюционировали, поэтому мне интересно, есть ли что-то новое и неисследованное в этой области? Любые стандартные предложения? OS-специфика? Хаки? Как вы пишете приложения, жаждущие памяти? Поделитесь своим опытом.