Я хотел бы заменить глобальное operator new()
и operator delete()
(наряду со всеми их вариантами), чтобы сделать некоторые приемы управления памятью. Я хотел бы, чтобы весь код в моем приложении использовал пользовательские операторы (включая код в моем собственном DLLs, а также стороннем DLLs). Я считал вещи о том, что компоновщик выберет первое определение, которое это видит при соединении (например, если библиотека, которая содержит пользовательское operator new()
связан сначала, это "разобьет" ссылку с CRT). Там некоторый путь состоит в том, чтобы гарантировать, что это произойдет? Что является правилами для этого, так как это действительно - умножение - определенный символ (например, void* operator new(size_t size)
имеют два определения в глобальном пространстве имен)?
Что относительно стороннего DLLs, который может быть статически связан с CRT? Даже если они динамично связаны с CRT, есть ли некоторый способ, которым я могу заставить их связываться с моим operator new()
?
Стандарт языка Си++ явно позволяет писать свой собственный глобальный оператор new и delete (и варианты массивов). Линкер должен заставить его работать, хотя именно так, как это зависит от реализации (например, такие вещи, как слабые экстерналы, могут быть полезны для поставки чего-то, если и только если его уже нет).
Что касается DLL, то это будет непросто: статически скомпонованная DLL явно не будет использовать ваш код без большой дополнительной работы. Статическая компоновка означает, что у нее уже есть копия кода библиотеки, скопированная в DLL, и любой код в DLL, который ее использовал, имеет адрес этого кода, уже закодированный. Чтобы обойти это, нужно выяснить, где находится код для нового в DLL, и динамически исправлять весь код, который вызывает его для вызова своего).
Если DLL динамически подключается к стандартной библиотеке, то это становится лишь незначительно проще - таблица импорта по-прежнему кодирует имя DLL и функцию в этой DLL, которая обеспечивает то, что ей нужно. Это можно обойти (например, с чем-то вроде библиотеки Microsoft Detours library), но это несколько нетривиально (хотя, конечно, проще, чем когда DLL связывает стандартную библиотеку статически).
Отредактируйте: После перевода вопроса я понимаю, что ваш акцент на сторонних компонентах. Так что в этом случае ответ нет. Есть слишком много переменных вовлеченных.
(Ссылаясь на замену «нового» в свой собственный код) Краткий ответ - да. Это общий трюк в системах, которые выполняют собственное управление памятью. Как вы, возможно, догадались, это очень сложная вещь, чтобы получить правильно, и может легко взорвать в своем лице, если вы не осторожны, но это, безусловно, правдоподобно и используется множеством программного обеспечения. (Я вспоминаю чтение некоторого кода, который делает это в Doom 3 SDK, например)
как для замены нового и удаления в третьей стороне DLL, это не произойдет (по крайней мере, безопасно). Для одного, откуда вы знаете, что они даже используют новые и удалять? Не говоря уже о том, что они могут выполнять свой собственный вариант этой техники и полагаться на некоторое побочное действие, чтобы функционировать правильно. И даже если вы получите его работать сейчас, откуда вы знаете, что некоторая будущая версия этого компонента не сломает это? Не стесняйтесь гадить с вашей собственной памятью все, что вы хотите, но ради вас и у вас семинан ваших пользователей, пожалуйста, не пытайтесь использовать микро-управление памятью других двоичных файлов.