7
votes

Redefine Malloc / Gratuit avec une liaison statique a une erreur de définition multiple

Récemment, mon entreprise souhaite mettre à jour le compilateur de GCC-3.4 à GCC-4.5. Cependant, la machine de notre client peut ne pas avoir le LIBSTDC ++ à jour. SO CODE>, donc nous voulons que nous souhaitons static Notre binaire.

Notre programme a besoin de personnalisé MALLOC () / gratuit ( ) code> pour une exigence très haute performance. p>

J'ai modifié le makefile, ajouté un -static code> lors de la liaison et du message d'erreur suivant: P>

/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)


3 commentaires

Bonjour @yoco, avez-vous eu une solution à la fin avec une liaison statique? J'ai le même problème.


@ user1147800 Je n'ai pas de solution de liaison statique. Je liens dynamique à la fin.


Vous pouvez statiquement lien libstdc ++. A et lien dynamique libc.so


6 Réponses :


0
votes

Très probablement, vous devrez modifier les noms de vos routines d'allocation personnalisées. Après cela, vous devez utiliser la méthode décrite dans la réponse pour gagner du temps afin que vous ne puissiez pas modifier tous les appels vers le nouveau nom:

#define malloc myMalloc
#define free myFree


1 commentaires

Merci pour votre réponse: D Mais l'idiome #define ne peut pas aider. J'avais éditer mon post.



2
votes

Vous devez utiliser votre propre fonction gratuite / Alloc / Realloc dans le projet, mais je vous conseille vivement d'utiliser le même nom que la bibliothèque standard.

Par exemple P>

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


2 commentaires

Je veux utiliser la bibliothèque standard. Mais veulent seulement remplacer le malloc / libre. Je lis maintenant le document GCC pour voir s'il y a une réponse.


Ensuite, vous devez définir votre propre fonction MALLOC avec un nom différent, car je l'écrivait et utilisez une macro pour redéfinir Malloc à votre propre fonction. Vous ne pouvez pas l'appeler MALLOC parce que vous aurez deux fonctions MALLOCLES différentes, la seule dans votre bibliothèque, et celle du LIBC.



5
votes

Si votre principale préoccupation est la disponibilité de libstdc ++. Donc, dans le système cible, pourquoi ne pas simplement distribuer la version plus récente de celle avec votre application?

Je pense que la liaison statique dans tous les cas n'est pas une bonne solution, la compilation du projet devient beaucoup plus difficile, et si vous utilisez vous-même des objets partagés vous-même (par exemple lors de l'utilisation de vos propres plug-ins), alors la liaison statique arrêterait simplement de travailler, Puisque une copie distincte de la bibliothèque statique devra être liée à chaque de vos fichiers binaires, exécutables et ainsi de suite. Et pouvez-vous imaginer ce qui se passe s'il y a plusieurs instances de variables globales, de verrous, etc. dans le même programme lorsqu'il est chargé? Je vais vous dire: Crashes.

Donc, ne faites pas de lien statique, copiez libstdc ++. Donc, à un répertoire privé (je ne sais pas où votre application est installée, mais s'il dispose d'un préfixe privé, c'est assez simple, utilisez $ préfixe / lib). < / p>

puis définissez ld_library_path ou utilisez -RPath pour encoder le chemin dans le binaire, de sorte que la liaison le trouve. Bien entendu, cela signifie que toutes les bibliothèques que vous connaissez, cela pourrait éventuellement utiliser LibstDC ++ aussi, doit également être distribuée avec votre application.

Mais taille-sage, il s'agit de la même chose, avec une liaison statique que vous porteriez ce code aussi.


1 commentaires

Merci, c'est exactement ce que j'ai besoin de résoudre mon problème. J'apprécie vraiment que vous savez ce que je veux même, je ne peux pas bien exprimer ma question.



1
votes

Utilisation pourrait utiliser gnu malloc hameçonne Si vous utilisez GNU Libc. Je ne suis pas si heureux du design de cette API, donc je ne recommande pas d'utiliser ceci.

Vous pouvez essayer de corriger libc. Supprimer tout le code dans MALLOC / et le remplacer par votre implémentation.

Utilisation de la même idée, vous pouvez essayer de prendre libc.a , supprimer tous les fichiers contenant masloc et amis ( Cela devrait être surtout tous les fichiers correspondant à masloc / *. C ) et reconditionnez libc.a avec votre implémentation.


1 commentaires

Merci. J'avais déjà interrogé cette solution. Mais en utilisant ce besoin de peu de travail de codage supplémentaire. La solution RPATH est donc meilleure pour moi: D



0
votes

Si vous n'avez besoin que de le faire pour C ++, vous pouvez remplacer les nouveaux opérateurs [] supprimer [] supprimer []. Voir 18.6.1 "Allocation de stockage et distribution" xxx

"remplaçable: Un programme C ++ peut définir une fonction avec cette signature de fonction qui déplace la version par défaut définie par la bibliothèque standard C ++."

Je ne sais pas si cela fonctionne avec une liaison statique cependant (ne sais pas comment elle est mise en œuvre).


0 commentaires

3
votes

Vous pouvez utiliser une liaison dynamique avec RPATH . Voir "Man LD" et "Man ld.so".

L'expansion $ origine peut être utile: assumez chaque .so dont vous avez besoin dans le même répertoire que le même répertoire que le programme (ou un sous-répertoire) et utilisez "-RPath $ Origine" ou "-RPath", $ Origin / Lib "lors de la liaison avec ld.

De nombreux programmes utilisent cette approche pour regrouper leurs propres libs privés.

L'autre moyen est d'utiliser un script .sh pour définir ld_library_path, puis appelez le programme réel (téléchargez Firefox binaire et regardez sur RUN-MOZILLA.SH). Cependant, le LD_Library_Path fuit les sous-processus. Il n'est donc pas aussi propre mais probablement plus portable pour les systèmes non GNU.


0 commentaires