Obtain the current stack information on Linux and Windows.

Source: Internet
Author: User

Obtain the current stack information on Linux and Windows.

The output stack information is often used when writing stable and reliable software services, so that users/developers can obtain accurate operation information. It is often used in log output, error reporting, and exception detection.

In Linux, there are simple functions to get stack information:

#include <stdio.h>#include <execinfo.h>#include <signal.h>#include <stdlib.h>#include <unistd.h>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 stackoverflow. The core function is backtrace and backtrace_symbols.

 

In Windows, StackWalker is recommended as the open source code. It supports X86, AMD64, and IA64.

If you need the simplest code, the code I extracted below is much more complex than Linux. (The implementation of many functions of Win is more complicated. Of course, many functions are much simpler than those of Linux .)

I will give some explanations later.

#include "stdafx.h"#include <Windows.h>#include <iostream>#include <DbgHelp.h>#include <TlHelp32.h>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 };        ctx.ContextFlags = CONTEXT_FULL;        RtlCaptureContext(&ctx);        STACKFRAME64 sf = { 0 };    #ifdef _M_IX86 // ignore IA64        auto 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_X64        auto 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;    #endif        MODULEENTRY32 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) + 100);        if (!sym)            return;        memset(sym, 0, sizeof(IMAGEHLP_SYMBOL64) + 100);        sym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);        sym->MaxNameLength = 100;        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[100];                if (sf.AddrPC.Offset != 0) {                    if (SymGetSymFromAddr64(ph, sf.AddrPC.Offset, &offset, sym)) {                        UnDecorateSymbolName(sym->Name, und_fullname, 100, 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);    }}int main(){    ph = GetCurrentProcess();    foo();    return 0;}

 

For compilation, please link dbghelp. lib

The core is StackWalk, SymGetSymFromAddr64, and SymGetLineFromAddr64.

StackWalk is used to obtain the next stack.

SymGetSymFromAddr64 is used to obtain the current function name.

SymGetLineFromAddr64 is used to obtain the file and row number of the function.

To ensure that the three functions work properly, you must initialize the SymInitialize function to obtain the current thread description table (RtlCaptureContext) and load the used modules (SymLoadModule64 ).

The <DbgHelp. h> <TlHelp32.h> header files are used.

After the above code is executed, stack information is output on the console.

 

Refer:

Https://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes

Http://www.codeproject.com/KB/threads/StackWalker.aspx

Related Article

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.