Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redefine malloc/free with static linking has multiple definition error

Recently, my company wants to update the compiler from gcc-3.4 to gcc-4.5. However, our customer's machine may not have the up-to-date libstdc++.so, so we want to static link our binary.

Our program needs customized malloc()/free() for very high performance requirement.

I modified the makefile, added a -static while linking, and got 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)

Ok, it is reasonablle, since libc.a already has malloc()/free().

But what confuses me is why there is no error while dynamic linking. I searched, and found this question: How to redefine malloc() in Linux for use in C++ new. The answer says the linker treats library file(.a) and object file(.o) differently. Now I know the reason why the error happens with static linking but not with dynamic.

However, I tried the solution described in that answer, replaced the library file with the object file directly, but there is no difference. I still got the multiple definition linking error. I also tried -static-libgcc (because I don't know what to do, I just tried everything I saw in gcc man page) but it does not help, too.

I do not have to use static linking. I just want to solve the libstdc++.so version problem. Any suggestion will be appreciated.

Thanks in advance.

edit: Sorry I did not make myself clear. Using #define malloc ... may not help here. Since our program is C++. The #define idiom can only affact the malloc()/free() function. But our program acutally uses new/delete to allocate/free memory. Thanks anyway :D

like image 658
yoco Avatar asked Apr 07 '11 05:04

yoco


3 Answers

If your primary concern is the availability of libstdc++.so in the target system, then why not simply distribute the newer version of that together with your application?

I think that static linking in any case is not a good solution, compiling the project becomes much harder, and if you are using shared objects yourself (for example when using your own plugins), then static linking would simply stop working, since a separate copy of the static library would need to be linked into each of your binaries, executable and so alike. And can you imagine what happens if there are multiple instances of global variables, locks etc in the same program when it gets loaded? I'll tell you: crashes.

So don't static link, copy libstdc++.so to a private directory (I don't know where your application is installed, but if it has a private prefix, that's quite simple, use $prefix/lib).

Then either set LD_LIBRARY_PATH, or use -rpath to encode the path into the binary, so that the linker finds it. Of course, then this means that all libraries that you link against, that could possibly use libstdc++ too, should also be distributed with your app.

But size-wise, it is about the same, with static linking you'd carry that code too.

like image 181
bazsi77 Avatar answered Sep 30 '22 15:09

bazsi77


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

The $ORIGIN expansion might be useful : bundle every .so you need in the same directory as the program (or a subdirectory) and use "-rpath $ORIGIN" or "-rpath,'$ORIGIN/lib" when linking with ld.

Many programs use this approach to bundle their own private libs.

The other way is to use a .sh script to set LD_LIBRARY_PATH and then call the real program (download firefox binary and look at run-mozilla.sh). However the LD_LIBRARY_PATH will leak to subprocesses. So it's not as clean but probably more portable to non GNU systems.

like image 31
ysdx Avatar answered Sep 30 '22 14:09

ysdx


You should use your own free/alloc/realloc function in the project, but i strongly advise you to use the same name as the standard library.

for example

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

You can combine it with a macro to redirect the allocation function to your fonction but i dont really adivse you to do it. you are obliged to check if all your source code include this header file, and the compiler can warmed you about macro redefinition (depending on the compiler and on the option you are using)

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

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

like image 43
Phong Avatar answered Sep 30 '22 13:09

Phong