开发者

Redefine malloc/free with static linking has multiple definition error

开发者 https://www.devze.com 2023-02-22 11:02 出处:网络
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.

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 fro开发者_运维百科m 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


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.


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.


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.


Use could use GNU malloc Hooks if you are using GNU libc. I'm not so happy with the design of this API so I don't recommend using this.

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

Using the same idea, you might try to to take libc.a, remove all the .o files containing malloc and friends (this should be mostly all the .o files corresponding to malloc/*.c) and repack libc.a with your implementation.


Most probably you'll need to change the names of you custom allocation routines. After that you should use the method described in the answer to save time so you don't have to change all the calls to the new name:

#define malloc myMalloc
#define free myFree


If you only need to do it for C++, you can override the new, delete, new[], delete[] operators. See 18.6.1 "Storage allocation and deallocation"

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

"Replaceable: a C++ program may define a function with this function signature that displaces the default version defined by the C++ standard library."

I don"t know if it works with static linking however (don't know how it is implemented).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号