2009-08-22 58 views
8

我试图找出一种方法来全局覆盖malloc和相关函数在visual c + +(2005年)。我的设置是一个静态链接的运行时库,包括我自己的C++代码,外部C++和c代码的dll。我想要完成的是允许dll的用户设置自己的内存分配函数的实现。全局覆盖视觉c + +中的malloc

的解决方案,我不能使用:

  • 重写新的和全球的删除, 有很多在 我的代码库,这意味着这不会 捕获许多分配外部C库。
  • 将malloc定义为不同的符号。这会迫使我将这个定义推送到所有外部库的构建设置中,我真的想避免这种情况。

事情我不关心

  • 如果任何外部库在其他一些方式分配内存(HeapAlloc,内存映射文件或任何他们拿出了),我接受这将不会通过重写malloc来正确跟踪。

最合理的解决方案,我可以拿出以某种方式与链接过程的干扰,并确保我自己的malloc被链接而不是标准的,最好我想能够使用旧的malloc作为默认功能。

在google perf-tools看来他们在运行时手动修补函数的代码,以允许在调用原函数之前调用一个钩子函数。这真的是这样做的最好方式吗?

+0

您是否试图在Linux上执行与LD_PRELOAD相同的操作? – LB40 2009-08-22 13:56:53

+0

我不熟悉LD_PRELOAD,但它似乎与动态链接有关,在我的情况下malloc,free和他们的朋友是静态链接的。 – Laserallan 2009-08-22 14:03:41

+0

你能解释为什么你认为你需要这样做吗? – 2009-08-22 15:40:26

回答

2

您可以使用Microsoft的Detours(支付商业用途)或重写您使用的dll的导入表。

+0

如果我使用动态链接运行时库,这肯定可以工作。但是,我担心我会重写使用我的库的可执行文件的函数。 – Laserallan 2009-08-22 14:59:20

+0

是的,你会的。这是一个全过程的事情。 – 2009-08-22 17:52:13

5

以下是Linux上的情况,但也可能适用于Win的Visual C++。

  1. Mallocitciton由系统库glibc提供。可执行文件默认与其链接。

  2. 运行该程序时,动态加载程序通知可执行文件需要malloc函数并查找提供它的第一个库。

  3. 由于glibc是(默认情况下)列表中的最后一个,所以找到的库可能不是glibc。

除非你静态链接的glibc到可执行文件,明显的解决方案是将可执行针对提供你自己的malloc链接库,并确保它覆盖系统的一个。

+0

这是正确的答案 – pgast 2009-08-22 15:58:46

+1

在Windows上不能这样工作。进口不只是名称而已。导入列出了每个需要提供它的DLL。 PE格式将允许您从两个DLL中导入相同的函数名称。 – MSalters 2009-08-25 14:19:51

+0

很酷,那么它只比linux中有点高 - 你实际上可以直接将函数分配给一个库,这样用户定义的malloc就会从特定的库中加载。这就是我们想要的,不是吗? – 2009-08-26 00:27:22

1

不幸的是,我对微软链接器不够了解。但是ld有' - wrap',你可以用它来做任何事情,比如malloc或free或其他任何东西(我这样做)。

所有对malloc的通话将被重定向到您已经实现了一个功能叫做--wrap malloc中调用,您可以再调用真正的malloc与__real_malloc。这也有利于捕获外部库中使用的任何malloc。我确定Microsoft链接器可能具有类似的功能。

+0

我没有在Visual Studio的链接器中找到类似的东西,最近我发现使用的是lib.exe工具(http://msdn.microsoft.com/en-us/library/7ykb2k5f(VS.71)。 ASPX)。它可以提取和添加.obj文件到一个静态库。从技术上讲,我可以使用修补过的malloc/calloc/free/realloc函数创建自己的标准库.lib文件。如果我刚找到一个可以重命名.obj文件中的函数的工具,可以重命名旧版本,并确保我的覆盖函数调用它们。 – Laserallan 2009-08-24 19:12:36

1

您可以使用lib.exe从lib中删除这些.obj文件。我不能更具体,但我确实记得当我从源代码构建Chromium时。

+0

您不是在暗示要操纵内置的Microsoft C++运行时库吗? – rustyx 2016-02-17 15:17:23

5

我很想找到一个很好的解决方案。我们为多种平台编译,所以在我们可以使用的非窗口方面 - 愉快地打包。我们只需要创建替换函数,并且所有工作都没有任何错误或黑客入侵。

在事物的窗口一侧,我们覆盖了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 Documentation

:d

+0

这看起来很有用。什么顺序的分辨率被使用?总是我自己的malloc是与标准库有冲突时使用的malloc吗?您是否通过自定义malloc将调用路由到原始定义,还是完全抛弃了标准库版本的malloc? – Laserallan 2009-08-30 12:32:04

+0

我们使用dlmalloc来做实际的分配。我的印象是,它会一直采用重写的功能,但现在你提出了这个问题,我不确定。 :D – 2009-09-02 09:04:43

1

删除所有包含使用的LIB工具的运行时库的内存管理功能的.obj文件,然后使用“忽略默认库”选项,在IDE和手动改为指定“你的”运行时库。然后编译;您应该会得到一些关于未定义的mallocfree等等的链接器错误。这是你进来的地方!

(您可能还希望做类似C++库的东西,如果你使用它们,但我觉得默认的operator new号召malloc所以你可能会去好,立竿见影。)

可视化Studio安装附带运行时间源代码(查看Visual Studio安装文件夹中的vc/crt/src),因此查找完整的内存管理功能集非常简单。我没有确切的细节(以前的雇主......),但是我记得,即使有比我预期的更多的内存分配功能,也只花了大约半天的时间来解决问题。

+0

谢谢,这似乎增加了最后一块拼图。 – Laserallan 2009-09-02 07:02:28

2

我使用的解决方案是从源代码重建Visual C++ C运行时库(crt)。

它可以在这里找到此文件夹中:

C:\ Program Files文件\微软的Visual Studio 9.0 \ VC \ CRT

确保您启动Visual Studio命令提示符来构建它。运行nmake足以启动它,尽管您可能想要确定要构建哪个目标,这意味着您必须了解makefile。

可能需要努力了解如何建立CRT,但一旦你拥有了它,你建设可以添加自己的代码到malloc的,免费和realloc等

不幸的是我还听到一个谣言,我们将无法从Visual Studio 2010开始的源代码构建crt。