Getting the current stack information on Linux and Windows

Source: Internet
Author: User

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, &AMP;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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.