When writing stable and reliable software services, output stack information is often used so that users/developers can obtain accurate operation information. Commonly used in log output, error reporting, and exception detection.
There are relatively simple functions to obtain stack information in Linux:
#include <> #include <> #include <> #include <> #include <> void handler(int sig) { void *array[5]; size_t size; // get void*'s for all entries on the stack size = backtrace(array, 5); // print out all the frames to stderr fprintf(stderr, "Error: signal %d:\n", sig); char** msgs = backtrace_symbols(array, size); for(int i=1;i<size && msgs[i];++i) printf("[%d] %s\n", i, msgs[i]); exit(1); } void baz() { int *foo = (int*)-1; // make a bad pointer printf("%d\n", *foo); // causes segfault } void bar() { baz(); } void foo() { bar(); } int main(int argc, char **argv) { signal(SIGSEGV, handler); // install our handler foo(); // this will call foo, bar, and baz. baz segfaults. }
The above code is slightly modified from the reference *. The core is two functions: backtrace and backtrace_symbols.
It is recommended to use StackWalker as an open source code for Windows, which supports X86, AMD64, and IA64.
If you need the simplest code, then below is the code I extracted, which is obviously more complicated than Linux. (Many of Win's functions are more complicated to implement, and of course there are many functions that are much simpler to implement than Linux.)
I will give some explanations later.
#include "" #include <> #include <iostream> #include <> #include <> using namespace std; HANDLE ph; void baz() { int* v = 0; *v = 0; } void bar() { baz(); } void foo(){ __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 }; = CONTEXT_FULL; RtlCaptureContext(&ctx); STACKFRAME64 sf = { 0 }; #ifdef _M_IX86 // ignore IA64 auto imageType = IMAGE_FILE_MACHINE_I386; = ; = AddrModeFlat; = ; = AddrModeFlat; = ; = AddrModeFlat; #elif _M_X64 auto imageType = IMAGE_FILE_MACHINE_AMD64; = ; = AddrModeFlat; = ; = AddrModeFlat; = ; = AddrModeFlat; #endif MODULEENTRY32 me; auto snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); auto info = Module32First(snap, &me); while (info) { auto dw = SymLoadModule64(ph, 0, , , (DWORD64), ); if (!Module32Next(snap, &me))break; } CloseHandle(snap); auto thread = GetCurrentThread(); PIMAGEHLP_SYMBOL64 sym = (IMAGEHLP_SYMBOL64 *)malloc(sizeof(IMAGEHLP_SYMBOL64) + 100); if (!sym) return; memset(sym, 0, sizeof(IMAGEHLP_SYMBOL64) + 100); sym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); sym->MaxNameLength = 100; IMAGEHLP_LINE64 line = { 0 }; = 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[100]; if ( != 0) { if (SymGetSymFromAddr64(ph, , &offset, sym)) { UnDecorateSymbolName(sym->Name, und_fullname, 100, UNDNAME_COMPLETE); cout << und_fullname; } if (SymGetLineFromAddr64(ph, , &offset_for_line, &line)) { cout << " " << << "(" << << ")"; } cout << endl; } } else break; } SymCleanup(ph); } } int main() { ph = GetCurrentProcess(); foo(); return 0; }
Please link to compile
The core is StackWalk, SymGetSymFromAddr64, SymGetLineFromAddr64.
StackWalk is used to get the next layer of stack.
SymGetSymFromAddr64 is used to get the current function name.
SymGetLineFromAddr64 is used to obtain the file and line number where the function is located.
In order for these three functions to work properly, the symbol-related function (SymInitialize) must be initialized, the current thread description table (RtlCaptureContext) must be obtained, and the module used is loaded (SymLoadModule64).
The two header files are used.
After the above code is executed, the stack information will be output on the console.
This article is the method to obtain the current stack information on Linux and Windows. It is all the content I share with you. I hope you can give you a reference and I hope you can support me more.