Wie können Sie CaptureStackBackTrace zur Erfassung der Ausnahme-stack, nicht die Aufruf-stack?

Markierte ich den folgenden code:

#include "stdafx.h"
#include <process.h>
#include <iostream>
#include <Windows.h>
#include "dbghelp.h"

using namespace std;

#define TRACE_MAX_STACK_FRAMES 1024
#define TRACE_MAX_FUNCTION_NAME_LENGTH 1024

int printStackTrace()
{
    void *stack[TRACE_MAX_STACK_FRAMES];
    HANDLE process = GetCurrentProcess();
    SymInitialize(process, NULL, TRUE);
    WORD numberOfFrames = CaptureStackBackTrace(0, TRACE_MAX_STACK_FRAMES, stack, NULL);
    SYMBOL_INFO *symbol = (SYMBOL_INFO *)malloc(sizeof(SYMBOL_INFO)+(TRACE_MAX_FUNCTION_NAME_LENGTH - 1) * sizeof(TCHAR));
    symbol->MaxNameLen = TRACE_MAX_FUNCTION_NAME_LENGTH;
    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    DWORD displacement;
    IMAGEHLP_LINE64 *line = (IMAGEHLP_LINE64 *)malloc(sizeof(IMAGEHLP_LINE64));
    line->SizeOfStruct = sizeof(IMAGEHLP_LINE64);
    for (int i = 0; i < numberOfFrames; i++)
    {
        DWORD64 address = (DWORD64)(stack[i]);
        SymFromAddr(process, address, NULL, symbol);
        if (SymGetLineFromAddr64(process, address, &displacement, line))
        {
            printf("\tat %s in %s: line: %lu: address: 0x%0X\n", symbol->Name, line->FileName, line->LineNumber, symbol->Address);
        }
        else
        {
            printf("\tSymGetLineFromAddr64 returned error code %lu.\n", GetLastError());
            printf("\tat %s, address 0x%0X.\n", symbol->Name, symbol->Address);
        }
    }
    return 0;
}

void function2()
{
    int a = 0;
    int b = 0;
    throw new exception;
}

void function1()
{
    int a = 0;
    function2();
}

void function0()
{
    function1();
}

static void threadFunction(void *param)
{
    try
    {
        function0();
    }
    catch (...)
    {
        printStackTrace();
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    _beginthread(threadFunction, 0, NULL);
    printf("Press any key to exit.\n");
    cin.get();
    return 0;
}

Was es tut, ist, meldet es einen stack-trace, aber das problem ist, dass der stack-trace protokolliert er gibt mir nicht die Zeilennummern, die ich will. Ich will, dass er log die Zeilen-Nummern der Plätze, die die Ausnahme ausgelöst hat, und auf den call-stack, der Art wie in C#. Aber was es tatsächlich tut, ist es gibt die folgenden:

        at printStackTrace in c:\users\<yourusername>\documents\visual studio 2013\pr
ojects\stacktracing\stacktracing\stacktracing.cpp: line: 17: address: 0x10485C0
        at threadFunction in c:\users\<yourusername>\documents\visual studio 2013\pro
jects\stacktracing\stacktracing\stacktracing.cpp: line: 68: address: 0x10457C0
        SymGetLineFromAddr64 returned error code 487.
        at beginthread, address 0xF9431E0.
        SymGetLineFromAddr64 returned error code 487.
        at endthread, address 0xF9433E0.
        SymGetLineFromAddr64 returned error code 487.
        at BaseThreadInitThunk, address 0x7590494F.
        SymGetLineFromAddr64 returned error code 487.
        at RtlInitializeExceptionChain, address 0x7713986A.
        SymGetLineFromAddr64 returned error code 487.
        at RtlInitializeExceptionChain, address 0x7713986A.

Das problem, das ich mich vor, wieder, ist, dass line: 68 in diese Spur bezieht sich auf die Zeile, die die Methode aufruft printStackTrace();, während ich es möchte, um mir die Linie Nummer 45, das entspricht der Linie, die die Ausnahme ausgelöst: throw new exception; und dann weiter oben im Stapel.

Wie kann ich erreichen, diese Art von Verhalten und brechen in diesem thread genau dann, wenn es wirft diese Ausnahme, um eine richtige stack-trace?

PS Der obige code ausgeführt wurde, für eine Konsolenanwendung, die mit MSVC++ mit unicode-fähig unter Windows 8.1 x64-Maschine, mit der die Anwendung ausgeführt wird, wie eine Win32-Anwendung im Debug-Modus.

  • Müssen Sie natürlich überspringen Sie die stack-frames, die Teil Ihrer logging-code. Einfach zählen Sie ab, __declspec(noinline) ist ratsam.
  • Aber dann wäre es einfach überspringen printStackTrace und threadFunction...und ließ mich mit beginthread, die, denke ich es nicht haben Zugriff auf die von der Kind-thread...siehe mein dilemma? Ich meine, nur um zu klären, Sie deuten die übergabe in eine übersprungene frame-Menge in den Ruf zu CaptureStackBackTrace(0, TRACE_MAX_STACK_FRAMES, stack, NULL); wie CaptureStackBackTrace(2, TRACE_MAX_STACK_FRAMES, stack, NULL); richtig? Seine immer noch nicht, was ich nach 😛
  • Sagen wir es so, ich will meinen stack trace zu gehören function2, function1, und function0. Vor allem function2 aber, und die Linie, an der die Ausnahme geworfen wird, an.
  • Das ist nicht möglich, wenn Sie verwenden catch(...), der Stapel ist schon abgewickelt und die Ausnahme abgetan. Müssen Sie SetUnhandledExceptionFilter() zum auffangen der nicht behandelte Ausnahme.
  • Es muss einen Weg, denn selbst, indem Sie eine vektorielle Ausnahme-handler ist es immer noch nicht mir der exakte Linie. Ich arbeite für ein Unternehmen, das keine stack-Trace in der Produktion (LOL), und ich muss hinzufügen, dass es in (offensichtlich die Leute zu faul sind es selbst zu tun, so dass alle die Arbeit bekommt verpfändet Weg für mich). Also ich bin auf der Suche nach einem Weg, um meine eigene stack-Trace-Bibliothek. Etwas kleines, einfach alle Ausnahmen abfangen und werfen einen stack-trace. Was empfehlen Sie? Und...warum in Gottes Namen ist es so schwer zu tun, dies in C++?!
  • PS ich will nicht verwenden StackWalker. Ich habe es nicht geschrieben, und soweit ich sagen kann, das ist fast das gleiche in Bezug auf die Funktionalität, die ich will, die einzige Sache ist, dass ich muss einen Weg finden, zu brechen, in einen thread, wenn eine Ausnahme geworfen wird, und der trace von dort; nicht nach der Ausnahme und nicht in jedem exception-handler / Verbraucher, denn das scheint nicht zu funktionieren.
  • stackoverflow.com/questions/19656946/...
  • Ich hätte zu verwenden, __try und __except und Holen Sie sich die Spur aus dem Kontext, dass...wie stack walker hat mit StackWalk64...ich wusste wirklich nicht wollen, um darüber zu gehen, wie dies seit der __try und __except funktioniert nicht, wenn gewickelt anderen try-catch-Blöcke...
  • Spin-Off, mehr Probleme...solche Kopfschmerzen. stackoverflow.com/questions/22481126/...
  • Am Ende, ich hatte zu schmücken alle Funktionen mit __declspec(noinline). Es hat funktioniert, und ich bekam eine neue Verständnis von inline-Methoden. Ich denke, wenn ich versuchte zunächst, ich habe nicht schmücken alle meine Methoden mit __declspec(noinline) - Richtlinie.
  • Tut mir Leid für die nicht die Anwendung Ihrer Konzepte vollständig, @HansPassant. Du bist verdammt gut in dem was Sie tun.

InformationsquelleAutor Alexandru | 2014-03-17
Schreibe einen Kommentar