Действительно ли возможно заменить глобальный “новый оператор ()” везде?

Я хотел бы заменить глобальное operator new() и operator delete() (наряду со всеми их вариантами), чтобы сделать некоторые приемы управления памятью. Я хотел бы, чтобы весь код в моем приложении использовал пользовательские операторы (включая код в моем собственном DLLs, а также стороннем DLLs). Я считал вещи о том, что компоновщик выберет первое определение, которое это видит при соединении (например, если библиотека, которая содержит пользовательское operator new() связан сначала, это "разобьет" ссылку с CRT). Там некоторый путь состоит в том, чтобы гарантировать, что это произойдет? Что является правилами для этого, так как это действительно - умножение - определенный символ (например, void* operator new(size_t size) имеют два определения в глобальном пространстве имен)?

Что относительно стороннего DLLs, который может быть статически связан с CRT? Даже если они динамично связаны с CRT, есть ли некоторый способ, которым я могу заставить их связываться с моим operator new()?

8
задан 20 January 2010 в 19:54
поделиться

2 ответа

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

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

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

7
ответ дан 5 December 2019 в 17:37
поделиться

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


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

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

3
ответ дан 5 December 2019 в 17:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: