Можно ли везде заменить глобальный оператор «new ()»? - PullRequest
8 голосов
/ 20 января 2010

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

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

Ответы [ 2 ]

7 голосов
/ 20 января 2010

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

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

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

3 голосов
/ 20 января 2010

РЕДАКТИРОВАТЬ: после перечитывания вопроса, я понимаю, что вы делаете акцент на сторонние компоненты. Так что в этом случае ответ - нет. Здесь задействовано слишком много переменных.


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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...