Redefine malloc / free with static link has multiple definition error

Recently, my company wants to upgrade the compiler from gcc-3.4 to gcc-4.5. However, our client machine may not have updated libstdc++.so , so we want to statically link our binary.

Our program needs to tune malloc()/free() for very high performance requirements.

I modified the makefile, added -static when linking, and received the following error message:

 /usr/lib64/libc.a(malloc.o)(.text+0x18c0): In function `free': : multiple definition of `free' ../../ic/src/memmgr/libmemmgr_mt_thread.a(memmgr_mt_thread.o)(.text+0x3430): first defined here /usr/bin/ld: Warning: size of symbol `free' changed from 271 in ../../ic/src/memmgr/libmemmgr_mt_thread.a(memmgr_mt_thread.o) to 255 in /usr/lib64/libc.a(malloc.o) /usr/lib64/libc.a(malloc.o)(.text+0x3970): In function `malloc': : multiple definition of `malloc' ../../ic/src/memmgr/libmemmgr_mt_thread.a(memmgr_mt_thread.o)(.text+0x29c0): first defined here /usr/bin/ld: Warning: size of symbol `malloc' changed from 281 in ../../ic/src/memmgr/libmemmgr_mt_thread.a(memmgr_mt_thread.o) to 461 in /usr/lib64/libc.a(malloc.o) /usr/lib64/libc.a(malloc.o)(.text+0x4050): In function `realloc': : multiple definition of `realloc' ../../ic/src/memmgr/libmemmgr_mt_thread.a(memmgr_mt_thread.o)(.text+0x3e80): first defined here /usr/bin/ld: Warning: size of symbol `realloc' changed from 335 in ../../ic/src/memmgr/libmemmgr_mt_thread.a(memmgr_mt_thread.o) to 927 in /usr/lib64/libc.a(malloc.o) 

Well, that’s reasonable, since libc.a already has malloc()/free() .

But what bothers me is that there are no errors with dynamic linking. I searched and found this question: How to override malloc () on Linux for use in C ++ new . The response says that the linker considers the library file (.a) and the object file (.o) differently. Now I know the cause of the error with static binding, but not with dynamics.

However, I tried the solution described in this answer, directly replaced the library file with the object file, but there is no difference. I still got a multiple definition binding error. I also tried -static-libgcc (because I don’t know what to do, I just tried everything I saw on the gcc man page), but that doesn’t help either.

I do not need to use static binding. I just want to solve the problem with the version of libstdc++.so Any suggestion would be appreciated.

Thanks in advance.

Edit: Sorry, I did not explain. Using #define malloc ... might not help. Since our program is C ++. The idiom #define can only use the malloc()/free() function. But our program uses new/delete to allocate / free memory. Thanks anyway: D

+7
source share
6 answers

If your main problem is the presence of libstdc ++, so on the target system, why not just distribute a newer version of this with your application?

I think that static linking is not a good solution anyway, compiling a project becomes much more difficult, and if you use shared objects yourself (for example, using your own plugins), static linking will simply stop working, since a separate copy of the static library should be linked in each of your binaries, executable and so similar. And can you imagine what will happen if there are several instances of global variables, locks, etc. in the same program when loading? I will tell you: failure.

So there is no static link, copy libstdC ++, therefore, to the private directory (I do not know where your application is installed, but if it has a private prefix, it is quite simple, use $ prefix / lib).

Then either set LD_LIBRARY_PATH, or use -rpath to encode the path in binary format so that the linker finds it. Of course, then this means that all the libraries you link to that could use libstdC ++ should also be distributed with your application.

But in size, it’s about the same, with a static link you also carry this code.

+5
source

You can use dynamic linking with rpath . See "man ld" and "man ld.so".

The $ ORIGIN extension can be useful: you need to bundle each .so in the same directory as the program (or subdirectory), and use "-rpath $ ORIGIN" or "-rpath", $ ORIGIN / lib when linking to ld.

Many programs use this approach to link their own private libraries.

Another way is to use a .sh script to set LD_LIBRARY_PATH and then call the real program (load the firefox binary file and view run-mozilla.sh). However, LD_LIBRARY_PATH will flow into subprocesses. Thus, this is not so clean, but probably more portable for non-GNU systems.

+3
source

You should use your own free / alloc / realloc function in the project, but I highly recommend that you use the same name as the standard library.

eg

 void* myProject_malloc(...) void myProject_free() 

You can combine it with a macro to redirect the distribution function to your function, but I really do not recommend you to do this. you should check if your entire source code has included this header file, and the compiler can keep warm about redefining macros (depending on the compiler and the parameter used).

 #define malloc(x) myProject_malloc(x) #define free() myProject_free() 

If you do not want to use the standard library, you should use the gcc: "-nostdlib" option. But if you do this, you cannot use any other function of the standard library.

+2
source

When using the GNU libc, use the GNU malloc hooks . I am not very happy with the design of this API, so I do not recommend using it.

You can try installing libc. Remove all code in malloc/ and replace it with your implementation.

Using the same idea, you can try to take libc.a , delete all .o files containing malloc and friends (this should be basically all .o files matching malloc/*.c ), and repack libc.a with your implementation .

+1
source

Most likely, you will need to change the names of your custom distribution procedures. After that, you should use the method described in the answer to save time, so you do not need to change all calls to a new name:

 #define malloc myMalloc #define free myFree 
0
source

If you need to do this only for C ++, you can override new, delete, new [], delete [] operators. See 18.6.1 “Allocating and Freeing Storage”

  void* operator new(std::size_t size); [...] void operator delete(void* ptr); 

"Replaceable: a C ++ program can define a function with this function signature, which offsets the default version defined by the C ++ standard library."

I don’t know if it works with static communication (I don’t know how this is implemented).

0
source

All Articles