Today, we have encountered such a requirement that the call stack can be printed out when an exception is thrown in the dynamic link library. I searched Google and found some clues. My file directory is as follows: the current directory is main. cpp and test/ Under test is a. h, A. cpp (defines a class), backtrace. H, backtrace. cpp Step 1: print the call stack. The backtrace function is implemented as follows: Backtrace. cpp # Include "backtrace. H" # Include <unistd. h> # Include <stdio. h> # Include <execinfo. h> # Include <stdlib. h> # Include <string. h> Void backtrace () { Const int maxlevel = 200; Void * buffer [maxlevel]; Int level = backtrace (buffer, maxlevel ); Const int size = 1024; Char cmd [size] = "addr2line-C-f-e "; // Let prog point to the end of "cmd" Char * prog = cmd + strlen (CMD ); Int r = readlink ("/proc/self/EXE", prog, sizeof (CMD)-(prog-cmd)-1 ); File * fp = popen (CMD, "W "); If (! FP) { Perror ("popen "); Return; } For (INT I = 0; I <level; ++ I) { Fprintf (FP, "% P/N", buffer [I]); } Fclose (FP ); } Main. cpp Include <stdio. h> # Include "A. H" # Include "backtrace. H" Void Foo (INT, char *) { Backtrace (); } Void bar (double) { Foo (0, null ); } Int main () { Bar (0.0 ); //; Return 0; } Compile as follows. Pay attention to the-G and-rdynamic parameters. [Charlie @ localhost so] $ g ++-g-rdynamic-itest main. cpp test/backtrace. cpp [Charlie @ localhost so] $./A. Out Backtrace () /Home/Charlie/workspace/SO/test/backtrace. cpp: 12 Foo (INT, char *) /Home/Charlie/workspace/SO/Main. cpp: 7 Bar (double) /Home/Charlie/workspace/SO/Main. cpp: 11 Main /Home/Charlie/workspace/SO/Main. cpp: 17 ?? ?? : 0 _ Start ?? : 0 From the above output, we can see that the call stack is correctly printed, including the function name, code file: number of rows Below ?? Indicates that the code file name cannot be obtained and may be filtered if necessary. Step 2: print the call stack in the dynamic link library. A. cpp # Include "A. H" # Include "backtrace. H" # Include <stdio. h> A: () { Printf ("A: A/N "); Backtrace (); } Related Changes in Main. cpp are as follows: Int main () { // Bar (0.0 ); A; Return 0; } Compile and generate a Dynamic Link Library: [Charlie @ localhost test] $ g ++-g-rdynamic-o liba. So-shared a. cpp backtrace. cpp
[Charlie @ localhost so] $ g ++-g-rdynamic-ltest-itest-La main. cpp [Charlie @ localhost so] $./A. Out A: ?? ?? : 0 ?? ?? : 0 Main /Home/Charlie/workspace/SO/Main. cpp: 7 ?? ?? : 0 _ Start ?? : 0 Unfortunately, only the main function can output the file name and number of rows. Dynamic Link Library cannot be typed out. Dynamic library does not work. How about static library? Intuition should be a line, because it is similar to the direct compilation link. CD to test, [Charlie @ localhost test] $ g ++-g-rdynamic-C backtrace. cpp A. cpp Compile and generate the. o file, and then use AR to compress it into the. A file. [Charlie @ localhost test] $ ar-rc liba. a. o backtrace. o [Charlie @ localhost test] $ CD .. [Charlie @ localhost so] $ g ++-g-rdynamic-itest main. cpp test/LIBA. [Charlie @ localhost so] $./A. Out A: Backtrace () /Home/Charlie/workspace/SO/test/backtrace. cpp: 12 A /Home/Charlie/workspace/SO/test/a. cpp: 9 Main /Home/Charlie/workspace/SO/Main. cpp: 17 ?? ?? : 0 _ Start ?? : 0 This execution really got the expected results and printed the stack information correctly. Conclusion: With the help of the addr2line command, backtrace can be used to display the function call stack information at runtime. This method is effective for static connections and does not work for dynamic libraries (not available for the moment ). |