2010-01-20 3 views
8

Я бы хотел заменить глобальные operator new() и operator delete() (наряду со всеми их вариантами), чтобы сделать некоторые трюки управления памятью. Я хотел бы, чтобы весь код в моем приложении использовал пользовательские операторы (включая код в моих собственных DLL, а также сторонние библиотеки DLL). Я прочитал вещи о том, что компоновщик выберет первое определение, которое он видит при связывании (например, если первая библиотека, содержащая ваш пользовательский operator new(), будет «бить» ссылку с ЭЛТ). Есть ли способ гарантировать, что это произойдет? Каковы правила для этого, так как это действительно многократно определенный символ (например, void* operator new(size_t size) имеет два определения в глобальном пространстве имен)?Можно ли повсеместно заменить глобальный «оператор new()»?

О сторонних DLL-экранах, которые могут быть статически связаны с CRT? Даже если они динамически связаны с ЭЛТ, есть ли какой-то способ, я могу связать их с моимoperator new()?

+6

Это чревато опасностью. Вы действительно хотите это сделать (y/N)? > –

+1

DLL - это двоичные файлы, поэтому они уже скомпилированы и связаны к моменту их получения. – KingRadical

+2

Достаточно честный. Я только спрашиваю, потому что мне будет плохо, если ваш следующий вопрос StackOverflow «как мне восстановить данные на очень важной производственной системе?» ;) –

ответ

7

Стандарт C++ явно позволяет вам писать свой собственный глобальный оператор new и delete (и варианты массива). Компилятор должен заставить его работать, хотя точно так же, как до разработчиков (например, такие вещи, как слабые внешние, могут быть полезны для поставки чего-то тогда и только тогда, когда его еще нет).

Что касается DLL, то это будет сложно: статически связанная DLL явно не будет использовать ваш код без большой дополнительной работы. Статическое связывание означает, что у него уже есть копия библиотечного кода, скопированного в DLL, и любой код в используемой DLL-адресе имеет адрес уже закодированного кода. Чтобы обойти это, вам нужно выяснить, где код для нового находится в DLL и динамически исправлять весь код, который вызывает его, вместо этого вызывать ваши).

Если DLL ссылается на стандартную библиотеку динамически, она становится чуть-чуть проще - таблица импорта по-прежнему кодирует имя DLL и функцию в этой DLL, которая обеспечивает то, что ему нужно. Это может быть достигнуто (например, с чем-то вроде Microsoft Detours library), но это несколько нетривиально (хотя, конечно, проще, чем когда DLL связывает стандартную библиотеку статически).

3

EDIT: После повторного чтения вопроса я понимаю, что ваш акцент делается на сторонних компонентах. Поэтому в этом случае ответ отрицательный. Есть слишком много переменных.


(Обращаясь к вопросу о замене «нового» на ваш собственный код) Короткий ответ - да. Это общий трюк в системах, которые выполняют собственное управление памятью. Как вы, возможно, догадались, это очень сложно сделать правильно, и может легко взорваться на вашем лице, если вы не будете осторожны, но это, безусловно, правдоподобно и используется множеством программного обеспечения. (Например, я читаю код, который делает это в Doom 3 SDK)

Что касается замены новых и удаления в сторонней DLL, это не произойдет (по крайней мере, не безопасно). Например, откуда вы знаете, что они даже используют новые и удаляют? Не говоря уже о том, что они могут делать свой собственный вариант этой техники и полагаться на некоторый побочный эффект, чтобы она функционировала должным образом. И даже если вы сейчас работаете, как вы знаете, что какая-то будущая версия этого компонента не сломает его? Не стесняйтесь гадать с вашей собственной памятью все, что хотите, но ради вас и ваших пользователей здравомыслие, пожалуйста, не пытайтесь микро-управлять памятью других двоичных файлов.

Смежные вопросы