In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article introduces the knowledge of "how to compile links". In the operation of actual cases, many people will encounter such a dilemma. Next, let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
I don't know whether dynamic link libraries are often used in programming. If a program references countless dynamic link libraries, it is possible to introduce the problem of symbol conflict. The questions are as follows:
In the imagination
Actually
Let's try to solve it:
At the beginning, the following basic command parameters are introduced:
Gmail +-c compiles the source file, but does not link-o specifies the name of the output file-s strip, removes symbol information-L instruction searches the path of the link library-l specifies the link library to be linked-shared produces a dynamic target file
Let's take a look at a piece of code:
# include void DoThing () {printf ("work\ n");}
Then define a simple main.cc program:
# include void DoThing (); int main () {printf ("start\ n"); DoThing (); printf ("finished\ n"); return 0;}
Compile the two files and package them into static libraries:
Gmail +-c work.cc-o work.o ar rc libwork.a work.o main.o ar rc libmain.a main.o +-c main.cc-o main.o ar rc libmain.a main.o
Now link the two static libraries into an executable file, and note that if the linker finds that undefined symbols are used in the current library, it will only look backwards, so libraries with no other dependencies at the lowest level should be placed on the far right. If there is a symbol conflict problem, the linker will use the leftmost symbol.
If you link like this:
$gathers +-s-L. -o main.exe-lwork-lmain. / libmain.a (main.o): In function `main': main.cc: (.text + 0x11): undefined reference to `DoThing () 'collect2: error: ld returned 1 exit status
The link failed because the DoThing symbol in the main library is not defined. The linker looks backward and does not find the corresponding symbol definition. Here, change the order of the link library:
Gathers +-s-L. -o main.exe-lmain-lwork $. / main.exe start work finished
Link successful.
Now write a simple file conflict.cc that is prone to symbol conflicts:
# include void DoThing () {printf ("conflict\ n");}
Compiled and packaged into static libraries:
Gmail +-c conflict.cc-o conflict.o ar rc libconflict.a conflict.o
If you link into an executable program in this order:
$gathers +-s-L. -o main.exe-lmain-lwork-lconflict $. / main.exe start work finished
If you change the order of the links slightly:
$gathers +-s-L. -o main.exe-lmain-lconflict-lwork $. / main.exe start conflict finished
It is found that the difference in order leads to different program output, which is due to the potential symbol conflict.
Now try dynamic libraries again, first introducing how to use dynamic libraries:
$rm libconflict.a $gathers +-shared conflict.o-o libconflict.so $gems +-s-L. -o main.exe-lmain-lconflict $LD_LIBRARY_PATH=. . / main.exe start conflict finished
Now refer to a middle tier's file layer.cc that calls conflict in the dynamic link library
# include void DoThing (); void DoLayer () {printf ("layer\ n"); DoThing ();}
And package layer and conflict into a dynamic link library:
$Gmail +-c layer.cc-o layer.o $Gmail +-shared layer.o conflict.o-o libconflict.so
Then update the main.c program. Call conflict in layer,layer in main:
# include void DoLayer (); int main () {printf ("start\ n"); DoLayer (); printf ("finished\ n"); return 0;}
Compile link execution:
$gathers +-c main.cc-o main.o $ar rc libmain.a main.o $gems +-s-L. -o main.exe-lmain-lconflict $LD_LIBRARY_PATH=. . / main.exe start layer conflict finished
Normal output, no problem. Now plug the previous work.cc into the main.cc to observe the conflict:
# include void DoThing (); void DoLayer (); int main () {printf ("start\ n"); DoThing (); DoLayer (); printf ("finished\ n"); return 0;}
Package work.o and main.o into a library, then link with conflict into an executable program, and run:
$gathers +-c main.cc-o main.o $ar rc libmain.a main.o work.o $gems +-s-L. -o main.exe-lmain-lconflict $LD_LIBRARY_PATH=. . / main.exe start work layer work finished
Here are two work output, normally the second work should output conflict, how to solve it? Consider using-fvisibility=hidden to hide the internal symbol, the symbol used inside the link library to hide it from being exported, and the external will not change its calling path.
First use nm to take a look at the symbols in libconflict.so:
$nm-CD libconflict.so w _ ITM_deregisterTMCloneTable w _ ITM_registerTMCloneTable 0000000000065a T DoLayer () 0000000000000672 T DoThing () 00000000201030 B _ bss_start w _ _ cxa_finalize w _ gmon_start__ 00000000201030 D _ edata 0000000000201038 B _ end 0000000000000688 T _ fini 0000000000000528 T _ init U puts
If you hide the symbol,
$gems +-fvisibility=hidden-c layer.cc-o layer.o $gems +-fvisibility=hidden-c conflict.cc-o conflict.o $gems +-shared layer.o conflict.o-o libconflict.so use nm again to look at the symbols in libconflict.so: $nm-CD libconflict.so w _ ITM_deregisterTMCloneTable w _ ITM_registerTMCloneTable 000000201028 B _ _ bss_start w _ cxa_finalize W _ _ gmon_start__ 0000000000201028 D _ edata 0000000000201030 B _ end 0000000000000618 T _ fini 00000000000004c0 T _ init U puts
In that case, the main function certainly cannot call DoLayer, because the DoLayer symbol is not exposed:
$gathers +-s-L. -o main.exe-lmain-lconflict. / libmain.a (main.o): In function `main': main.cc: (.text + 0x16): undefined reference to `DoLayer () 'collect2: error: ld returned 1 exit statu
So how do you expose specific symbols? look directly at the code and change the layer.cc:
# include void DoThing (); _ _ attribute__ ((visibility ("default") void DoLayer () {printf ("layer\ n"); DoThing ();}
Then compile the link and run it to see the result:
$Gmail +-fvisibility=hidden-c layer.cxx-o layer.o $Gmail +-shared layer.o conflict.o-o libconflict.so $Gmail +-s-L. -o main.exe-lmain-lconflict $LD_LIBRARY_PATH=. . / main.exe start work layer conflict finished
Discovery is already the result we expect, and the problem of symbolic conflict is solved.
Does it feel troublesome? should every symbol to be exposed have to be modified by _ _ attribute__? you can actually write an export file here to tell the compiler what all the symbols are to be exported.
Export.txt {global: * DoLayer*; local: *;}; libconflict.so +-Wl,--version-script=export.txt-s-shared layer.o conflict.o-o libconflict.so
But this method can only be used in gcc. I tried to use it in clang but failed, so for compatibility, it is not recommended to use _ _ attribute__ to solve the problem of symbol conflict.
This is the end of how to compile links. Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.