views:

267

answers:

3

In our application (older parts) we alter calls to malloc (and realloc) and free so our own implementations are called instead of the standard runtime ones, e.g.

#define malloc(s) OurMalloc(s)
#define free(p)   OurFree(p)

This works quite good (for newer C++ code we simply implement global new and delete operators, so the C++ solution is 'cleaner').

The problem is that we now have to include a 3rd party library, which has classes that contain methods that have names like malloc and free, e.g.

class ABC
   {
   public:
      ...
      void free (char *p);
   };

If the free method of the class has the same number of arguments, the C/C++ preprocessor simply replaces all occurrences of free by ourFree, even in the class definition, even when calling the method free of the class ABC. So the class definition above and the following call:

ABC abc;
abc.free(p);

are replaced by:

class ABC
   {
   public:
      ...
      void OurFree (char *p);
   };

ABC abc;
abc.OurFree(p);

Which may compile, but which doesn't link of course.

If ABC::free has a different number of arguments than the standard free, the compiler still gives a warning (which we want to avoid).

Some alternative solutions are:

  • undefining our defines in the beginning of the 3rd party include file and redefining it later
  • make sure that the 3rd party include file is always included before our own define's

But even then, if our code is required to call these malloc or free methods of the 3rd party classes, the preprocessor will still alter the calls, unless we write all calls like this:

(abc::free)(p)

Is there a way to tell a C/C++ preprocessor define that?

  • only pure C-calls must be replaced
  • prototypes MUST NOT be replaced
  • methods in classes MUST NOT be replaced
+2  A: 

How about only defining those replacements for C and not C++:

#ifndef __cplusplus
#  define malloc(s) OurMalloc(s)
#  define free(p)   OurFree(p)
#endif
Nikolai N Fetissov
This doesn't help as all the code is compiled as C++ code, even the older C-only parts.
Patrick
Then just replace top-level malloc and remove all the pre-processor games.
Nikolai N Fetissov
A: 

Preprocessor know nothing about about scope and semantic. So short answer - no, you can't do that.

But, you can use #undef free in library modules. On other side - this will not help, if you call methods abc.free() from your code.

werewindle
I'm afraid this was the answer.
Patrick
+1  A: 

Why don't you just define your own malloc and free functions instead of using macros.

So, change:

void *OutMalloc (size_t s)

to:

void *malloc (size_t s)

in the same way that you can overright operator new and delete.

I think, although I may be wrong, the linker will look in object files for symbols before looking in libraries.

Skizz
We used to do this in the past, but this only works if you statically link in the C/C++ run time libraries (and you pass your own 'overruled' object files to the linker before the run time library). It doesn't work if you dynamically link with the C/C++ run time DLL's.
Patrick
Doesn't Windows have something along the lines of LD_PRELOAD?
Nikolai N Fetissov
LD_PRELOAD seems to be Unix only, not Windows. Although I found some useful information related to DLL injection.
Patrick