Output stack information is often used when writing robust software services so that the user/developer can obtain accurate information about the operation. Commonly used in log output, error reporting, anomaly detection.
There are simpler functions in Linux to get stack information:
#include <stdio.h>#include<execinfo.h>#include<signal.h>#include<stdlib.h>#include<unistd.h>voidHandlerintSIG) { void*array[5]; size_t size; //get void* ' s for all entries on the stackSize = BackTrace (Array,5); //Print out all the frames to stderrfprintf (stderr,"error:signal%d:\n", SIG); Char* * Msgs =backtrace_symbols (array, size); for(intI=1; I<size && msgs[i];++i) printf ("[%d]%s\n", I, msgs[i]); Exit (1);}voidBaz () {int*foo = (int*)-1;//Make a bad pointerprintf"%d\n", *foo);//causes Segfault}voidBar () {Baz ();}voidfoo () {bar ();}intMainintargcChar**argv) {Signal (SIGSEGV, handler); //Install our handlerFoo ();//This would call Foo, bar, and Baz. Baz Segfaults.}
The above code is slightly modified from the reference StackOverflow. The core is the two functions of BackTrace and Backtrace_symbols.
Under Windows recommended stackwalker This open source code, support X86,amd64,ia64.
If you need a minimalist code, the following is the code I extracted, obviously more complicated than Linux. (Win's many features are more complex to implement, but there are also many features that are much simpler to implement than Linux.) )
I'll do some explaining, in the back.
#include"stdafx.h"#include<Windows.h>#include<iostream>#include<DbgHelp.h>#include<TlHelp32.h>using namespacestd; HANDLE ph;voidBaz () {int* v =0; *v =0;}voidBar () {Baz ();}voidfoo () {__try {bar (); } __except (Exception_execute_handler) {Auto Sire= syminitialize (ph,0, FALSE); Sire= Symsetoptions (symgetoptions () | Symopt_load_lines |symopt_fail_critical_errors); CONTEXT CTX= {0 }; CTx. Contextflags=Context_full; Rtlcapturecontext (&CTX); STACKFRAME64 SF= {0 }; #ifdef _m_ix86//Ignore IA64Auto ImageType =image_file_machine_i386; sf. Addrpc.offset=CTX. Eip; sf. Addrpc.mode=Addrmodeflat; sf. Addrframe.offset=CTX. EBP; sf. Addrframe.mode=Addrmodeflat; sf. Addrstack.offset=CTX. ESP; sf. Addrstack.mode=Addrmodeflat; #elif_m_x64Auto ImageType=image_file_machine_amd64; sf. Addrpc.offset=CTX. Rip; sf. Addrpc.mode=Addrmodeflat; sf. Addrframe.offset=CTX. RSP; sf. Addrframe.mode=Addrmodeflat; sf. Addrstack.offset=CTX. RSP; sf. Addrstack.mode=Addrmodeflat; #endifMODULEENTRY32 me; Auto Snap=CreateToolhelp32Snapshot (Th32cs_snapmodule, GetCurrentProcessId ()); Auto Info= Module32first (SNAP, &me); while(info) {Auto DW= SymLoadModule64 (ph,0, Me.szexepath, Me.szmodule, (DWORD64) me.modbaseaddr, me.modbasesize); if(! Module32next (SNAP, &me)) Break; } closehandle (SNAP); Auto Thread=GetCurrentThread (); Pimagehlp_symbol64 sym= (Imagehlp_symbol64 *)malloc(sizeof(IMAGEHLP_SYMBOL64) + -); if(!sym)return; memset (Sym,0,sizeof(IMAGEHLP_SYMBOL64) + -); Sym->sizeofstruct =sizeof(IMAGEHLP_SYMBOL64); Sym->maxnamelength = -; Imagehlp_line64 Line= {0 }; Line. Sizeofstruct=sizeof(line); for (;;) {Auto result= Stackwalk (imageType, ph, thread, &SF, &ctx,0, SymFunctionTableAccess64, SymGetModuleBase64,0); if(Result) {DWORD64 offset=0; DWORD Offset_for_line=0; CHAR und_fullname[ -]; if(SF. Addrpc.offset! =0) { if(SymGetSymFromAddr64 (ph, sf.) Addrpc.offset, &offset, sym)) {Undecoratesymbolname (sym->name, Und_fullname, -, Undname_complete); cout<<Und_fullname; } if(SymGetLineFromAddr64 (ph, sf.) Addrpc.offset, &offset_for_line, &Line )) {cout<<" "<< line. FileName <<"("<< line. LineNumber <<")"; } cout<<Endl; } } Else Break; } symcleanup (ph); }}intMain () {ph=getcurrentprocess (); Foo (); return 0;}
Compile please link dbghelp.lib
The core is Stackwalk and symgetsymfromaddr64,symgetlinefromaddr64.
The stackwalk is used to get the next layer of stack.
The SymGetSymFromAddr64 is used to get the current function name.
SymGetLineFromAddr64 is used to get the file and line number where the function resides.
For these three functions to work properly, also initialize the symbol-related function (syminitialize), get the current thread description table (rtlcapturecontext), load the module (SYMLOADMODULE64).
Used <DbgHelp.h> <TlHelp32.h> these two header files.
The above code executes after the stack information is output in the console.
Reference:
Https://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes
Http://www.codeproject.com/KB/threads/StackWalker.aspx
Getting the current stack information on Linux and Windows