Глобально переопределить malloc в Visual C ++ - PullRequest
10 голосов
/ 22 августа 2009

Я пытаюсь найти способ глобально переопределить malloc и связанные функции в Visual C ++ (2005). Моя установка представляет собой dll со статически связанной библиотекой времени выполнения, которая состоит из моего собственного кода c ++, внешнего кода c ++ и c. Чего я хочу добиться, так это позволить пользователю dll устанавливать свои собственные реализации функций выделения памяти.

Решения, которые я не могу использовать:

  • Переопределение новых и удаление глобально, есть много внешних библиотек C в моя база кода, что означает, что это не будет захватить много распределений.
  • определение malloc для другого символа. Это заставило бы меня вставить это определение в настройки сборки всех используемых внешних библиотек, и я действительно хочу этого избежать.

Вещи, которые меня не волнуют

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

Самое разумное решение, которое я могу придумать, - это каким-то образом вмешиваться в процесс компоновки и убедиться, что мой собственный malloc связан со стандартными, желательно, чтобы я мог использовать старые функции malloc по умолчанию. .

В google perf-tools кажется, что они исправляют код функций вручную во время выполнения, чтобы позволить вызывать функцию ловушки перед вызовом исходной функции. Это действительно лучший способ сделать это?

Ответы [ 7 ]

7 голосов
/ 27 августа 2009

Я тоже хочу найти подходящее решение для этого. Мы компилируем для нескольких платформ, так что мы можем с радостью использовать не входящие в Windows стороны. Нам просто нужно создать функции замены, и все это работает без ошибок или взломов.

Что касается окон, мы переопределяем вызовы malloc, но затем используем /FORCE:MULTIPLE для устранения ошибок компоновщика. Работает, функции памяти вызываются и все отслеживается, но похоже на взлом.

Из MSDN:

A file created with this option may not run as expected. The linker will not link incrementally when the /FORCE option is specified.

Мало того, что это похоже на хак, оно убивает редактирование и продолжает процесс.

Опция /FORCE:MULTIPLE может решить ваши проблемы, но я не предлагаю это как лекарство, я все еще пытаюсь найти это.

Документация MSDN / FORCE

: D

5 голосов
/ 22 августа 2009

Следующее верно для Linux, но может быть применимо и к Visual C ++ в Win.

  1. Функция Malloc предоставляется системной библиотекой glibc. Исполняемый файл по умолчанию связан с ним.

  2. При запуске программы динамический загрузчик замечает, что исполняемый файл нуждается в функции malloc, и ищет первую библиотеку, которая ее предоставляет.

  3. Так как glibc является (по умолчанию) последним в этом списке, найденная библиотека может быть не glibc.

Если вы не статически связали glibc с исполняемым файлом, очевидным решением будет связать исполняемый файл с библиотекой, которая предоставляет ваш собственный malloc, и убедитесь, что он переопределяет системный.

2 голосов
/ 29 апреля 2010

Решение, которое я использовал, - это перестройка библиотеки времени выполнения Visual C ++ C (crt) из исходного кода.

Его можно найти в этой папке:

C: \ Program Files \ Microsoft Visual Studio 9.0 \ VC \ crt

Убедитесь, что вы запустили командную строку Visual Studio для его сборки. Чтобы запустить сборку, достаточно запустить nmake, хотя вы можете решить, какую цель собрать, и это означает, что вам придется разбираться в make-файле.

Может потребоваться усилие, чтобы понять, как построить crt, но как только вы его построите, вы можете добавить свой собственный код в malloc, free и realloc и т. Д.

К сожалению, я слышал слух, что мы не сможем собрать crt из исходного кода, начиная с Visual Studio 2010.

2 голосов
/ 22 августа 2009

Вы можете использовать Обходы от Microsoft (оплата за рекламу) или переписать таблицы импорта для используемых вами DLL.

1 голос
/ 02 сентября 2009

Удалите все файлы .obj, которые содержат функции управления памятью, из библиотек времени выполнения с помощью инструмента LIB, затем используйте опцию «Игнорировать библиотеки по умолчанию» в IDE и вместо этого вручную укажите «свою» библиотеку времени выполнения. Затем скомпилируйте; вы должны получить несколько ошибок компоновщика о неопределенных malloc и free и так далее. Это где вы входите!

(Вы, вероятно, также захотите сделать что-то похожее на библиотеки C ++, если будете их использовать, хотя я думаю, что вызов operator new s по умолчанию malloc, так что вам, возможно, будет хорошо сразу пойти.)

Установка Visual Studio поставляется с исходным кодом среды выполнения (см. vc/crt/src в папке установки Visual Studio), поэтому найти полный набор функций управления памятью довольно просто. У меня нет точных деталей (предыдущий работодатель ...), но, насколько я помню, на разборку у меня ушло всего около полдня, хотя там было гораздо больше функций выделения памяти, чем я ожидал.

1 голос
/ 25 августа 2009

Вы можете удалить эти .obj файлы с помощью lib.exe из lib. Я не могу быть более конкретным, но я помню, как делал это, когда строил Chromium из исходного кода.

1 голос
/ 22 августа 2009

К сожалению, я не знаю достаточно о компоновщике Microsoft. Но у ld есть «--wrap», который вы можете использовать для чего угодно, например, malloc, free или для чего-либо еще (я делаю это).

все вызовы malloc будут перенаправлены в функцию с именем __wrap_malloc, которую вы реализовали, затем вы можете вызвать real malloc с помощью __real_malloc. Это имеет преимущество захвата любых mallocs, используемых во внешних библиотеках. Я уверен, что компоновщик Microsoft может иметь аналогичную функцию.

...