简体   繁体   English

C ++堆栈跟踪奇数

[英]C++ Stack Tracing Oddity

Following advice from here and here , I created a class to print the call stack, with line numbers, just by inserting a call at a point in my code. 遵循这里此处的建议,我创建了一个类,通过在代码中的某个点插入一个调用来打印带有行号的调用堆栈。 It works well enough, but, I am confused by one aspect of the output - the line number. 它工作得很好,但是我对输出的一个方面(行号)感到困惑。 My test code: 我的测试代码:

#define _WIN32 1
#define DEBUG 1

#include "C:\git\StackTrace\StackTrace.h"

int main()
{
    MyCompany::PrintStackTrace();
    return 0;
}

The call to print the stack trace is on line 8 , however, the output indicates it's on line 9 : 打印堆栈跟踪的调用在第8行,但是输出表明它在第9行:

*** 0: main in c:\git\tests\stacktrace\stacktrace\st_test.cpp: line: 9: address: 0x7FF629172070
*** 1: invoke_main in f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl: line: 41: address: 0x7FF629173710
*** 2: __scrt_common_main_seh in f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl: line: FD: address: 0x7FF6291734C0
*** 3: __scrt_common_main in f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl: line: 128: address: 0x7FF6291734A0
*** 4: mainCRTStartup in f:\dd\vctools\crt\vcstartup\src\startup\exe_main.cpp: line: 11: address: 0x7FF629173760
*** SymGetLineFromAddr64 returned error code 487
*** at BaseThreadInitThunk address 0x7FFA09648350
*** SymGetLineFromAddr64 returned error code 487
*** at RtlUserThreadStart address 0x7FFA0BF070B0

Please help me understand what I am missing here? 请帮助我了解我在这里缺少什么?

My StackTrace.h code: 我的StackTrace.h代码:

#ifdef _WIN32
#ifdef DEBUG

#include <Windows.h>
#include <fstream>
#include <iostream>
#include <DbgHelp.h>
#include <WinBase.h>

#pragma comment(lib, "Dbghelp.lib")

using namespace std;

namespace MyCompany
{
    class StackTrace
    {
    private:
        static bool instanceFlag;
        static StackTrace *single;
        StackTrace() { }
    public:
        static StackTrace* GetInstance();
        void PrintStack();
        void PrintStack(ostream& out, int skipFrames);
        ~StackTrace()
        {
            instanceFlag = false;
        }
    };

    bool StackTrace::instanceFlag = false;
    StackTrace* StackTrace::single = NULL;

    /**
     * Returns the instance of the StackTrace class, generating the instance if needed.
     *
     * @return A pointer to the instance of the StackTrace class.
     */
    StackTrace* StackTrace::GetInstance()
    {
        if (!instanceFlag)
        {
            single = new StackTrace();
            instanceFlag = true;
            return single;
        }
        else
        {
            return single;
        }
    }

    /**
     * Prints the call stack to stdout.
     *
     * @param sourceStr
     *        The multibyte character string.
     */
    void StackTrace::PrintStack()
    {
        // If PrintStackTrace() was called with no parameters, there is one more 
        // wrapper in the stack (this one) to skip.
        int skipFrames = 3;

        PrintStack(cout, skipFrames);
    }

    /**
     * Prints the call stack to the given stream.
     *
     * @param out
     *        The already-opened stream where the call stack will be printed.
     *
     * @param skipFrames
     *        The number of frames to skip when capturing the call stack.
     */
    void StackTrace::PrintStack(ostream& out, int skipFrames = 2)
    {
        const int maxCallers = 1024; // Not worried about size limits of OS's older than Windows 7.
        void * callers_stack[maxCallers];
        unsigned short frames;
        SYMBOL_INFO * symbol;
        HANDLE process;
        DWORD displacement;

        IMAGEHLP_LINE64 *line = (IMAGEHLP_LINE64 *)malloc(sizeof(IMAGEHLP_LINE64));
        if (NULL == line)
        {
            return;
        }

        process = GetCurrentProcess();
        SymInitialize(process, NULL, TRUE);
        frames = CaptureStackBackTrace(skipFrames, maxCallers, callers_stack, NULL);

        symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
        if (NULL == symbol)
        {
            return;
        }

        symbol->MaxNameLen = 255;
        symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

        out << uppercase;

        const unsigned short  MAX_CALLERS_SHOWN = 64;
        frames = frames < MAX_CALLERS_SHOWN ? frames : MAX_CALLERS_SHOWN;

        for (unsigned int i = 0; i < frames; i++)
        {
            DWORD64 address = (DWORD64)(callers_stack[i]);
            SymFromAddr(process, address, 0, symbol);

            if (SymGetLineFromAddr64(process, address, &displacement, line))
            {
                out << "*** " << dec << i << ": " << symbol->Name << " in " << line->FileName 
                    << ": line: " << line->LineNumber << ": address: 0x" << hex << symbol->Address << endl;
            }
            else
            {
                out << "*** SymGetLineFromAddr64 returned error code " << dec << GetLastError() << endl;
                out << "*** at " << symbol->Name << " address 0x" << hex << symbol->Address << endl;
            }
        }

        if (symbol) free(symbol);
        if (line) free(line);
    }

    /**
     * Print the call stack to stdout.
     */
    void PrintStackTrace()
    {
        StackTrace::GetInstance()->PrintStack();
    }

    /**
     * Print the call stack to the given stream.
     *
     * @param out
     *        The already-opened stream where the call stack will be printed.
     */
    void PrintStackTrace(ostream& out)
    {
        StackTrace::GetInstance()->PrintStack(out);
    }
}

#endif // DEBUG
#endif // _WIN32

You can't expect line numbers to be completely reliable - not even the stack trace itself for that matter. 您不能指望行号是完全可靠的-甚至堆栈跟踪本身也不会。 Once the optimizer is done chewing on your code it will look very different to what you actually wrote and there's only so much info that can be kept in debug info to map it back to source. 一旦优化器完成了对代码的咀嚼,它看起来将与您实际编写的代码完全不同,调试信息中只能保留太多信息,以将其映射回源代码。

You have to learn to read stack traces with a grain of salt. 您必须学习阅读带有一粒盐的堆栈跟踪信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM