views:

1279

answers:

7

Hi!

I'm trying to figure out a way to globally override malloc and related functions in visual c++ (2005). My setup is a dll with statically linked runtime library that consists of both my own c++ code, external c++ and c code. What I want to accomplish is to allow a user of the dll to set their own implementations of the memory allocation functions.

Solutions that I can't use:

  • Overriding new and delete globally, there is lots of external C libraries in my code base which means this won't capture many allocations.
  • #defining malloc to a different symbol. This would force me to push this define into the build settings of all external libraries used and I really want to avoid this.

Things I don't care about

  • If any of the external libraries are allocating memory in some other way (HeapAlloc, memory mapped files or whatever they come up with), I accept that this won't be tracked properly by overriding malloc.

The most reasonable solution I can come up with is somehow interfering with the link process and making sure my own malloc is being linked instead of the standard ones, preferably I'd like to be able to use the old malloc functions as default.

In google perf-tools it seems like they patch the code of the functions manually at runtime to allow a hook function to be called before calling the original function. Is this really the best way of doing this?

+1  A: 

You can use Detours from Microsoft (pay for commercial) or rewrite the import tables for the dlls you use.

jeffamaphone
This could definitely work if I used the dynamically linked runtime library. However, I'm worried that I'd override the functions for the executable using my library as well.
Laserallan
Yes, you would. It's a process-wide thing.
jeffamaphone
+2  A: 

The following is true on Linux, but may be applicable to Win's visual C++ as well.

  1. Malloc funciton is provided by system library glibc. The executable is by default linked against it.

  2. When the program is run, the dynamic loader notices that executable needs malloc function and looks for the first library that provides it.

  3. As glibc is (by default) the last in that list, the library found may not be glibc.

Unless you have statically linked glibc into the executable, the obvious solution is to link the executable against the library that provides your own malloc, and make sure that it does override the system's one.

Pavel Shved
this is the correct answer
pgast
Doesn't work that way on Windows. Imports are not by name only. Imports are listed per DLL that needs to provide it. The PE format would allow you to import the same function name from two DLLs.
MSalters
Cool, then it's just a bit _superior_ than it's in linux - you actually can directly assign the function to a library, so that a user-defined malloc will get loaded from a specific library. That's what we want, isn'\t it?
Pavel Shved
+1  A: 

Unfortunately I don't know enough about the microsoft linker. But ld has '--wrap' which you can use for anything like malloc or free or anything else (I do this).

all calls to malloc will be redirected to a function called __wrap_malloc which you have implemented, you can then call real malloc with __real_malloc. This has the benefit of capturing any mallocs used in external libraries too. I'm sure the Microsoft linker might have a similar function.

Salgar
I didn't find anything like that in the visual studio linker and the closest I found is using the tool lib.exe (http://msdn.microsoft.com/en-us/library/7ykb2k5f(VS.71).aspx). It can extract and add .obj files to a static library. Technically I could create my own version of the standard library .lib file with patched malloc/calloc/free/realloc functions. If I just found a tool that can rename functions inside an .obj file it would be possible to rename the old versions and make sure my override functions calls them.
Laserallan
+1  A: 

You can remove those .obj files with lib.exe from lib. I can't be more specific but I do remember doing it when I was building Chromium from source.

TheBlack
+1  A: 

I'm keen to find a neat solution for this too. We compile for multiple platforms, so on the non-windows side of things we can use --wrap happily. We just have to create the replacement functions and it all works without any errors or hacks.

On the windows side of things, we override the malloc calls, but then use /FORCE:MULTIPLE to deal with the linker errors. It works, the memory functions are called and everything is tracked, but it feels like a hack.

From MSDN:

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

Not only does it feel like a hack, it kills edit and continue in the process.

The /FORCE:MULTIPLE option might fix your problems, but I'm not suggesting it as a cure, I'm still trying to find that.

MSDN /FORCE Documentation

: D

Danny Parker
This looks useful. What order of resolution is used? Will always my own malloc is the one used when there is a conflict with the standard library? Do you route the calls through your custom malloc to the original definition or did you throw out the standard library version of malloc completely?
Laserallan
We are using dlmalloc to do the actual allocations. I'm under the impression that it will always take the overridden functions, but now you've posed the question, I'm not sure.: D
Danny Parker
+1  A: 

Remove all of the .obj files that contain memory management functions from the runtime libraries using the LIB tool, then use the "Ignore default libraries" option in the IDE and manually specify "your" runtime library instead. Then compile; you should get a few linker errors about undefined malloc and free and so on. This is where you come in!

(You'll probably also want to do something similar to the C++ libraries if you use them, though I think the default operator news call malloc so you might be good to go straight away.)

The Visual Studio install comes with the runtime source code (look in vc/crt/src in your Visual Studio install folder), so finding the full set of memory management functions is fairly straightforward. I don't have exact details to hand (previous employer...) but as I recall, it only took about half a day to sort out even though there were rather more memory allocation functions than I expected.

brone
Thanks, this seems to add the last piece of the puzzle.
Laserallan
+1  A: 

A solution I have used is to rebuild the Visual C++ C runtime library (crt) from source code.

It can be found here in this folder:

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

Make sure you start up the Visual Studio command prompt to build it. Running nmake is enough to start it building although you might want to work out which target to build and this means you will have to understand the makefile.

It may take an effort to understand how to build the crt, but once you have it building you can add your own code into malloc, free and realloc, etc.

Unfortunately I have heard a rumour that we won't be able to build the crt from source code starting with Visual Studio 2010.

Ashley Davis