0

In C#, you get the following type of stack trace:

   at ExceptionGenerator.Program.three() in c:\Users\ADIMA\Documents\Visual Stud
io 2013\Projects\ExceptionGenerator\ExceptionGenerator\Program.cs:line 36
   at ExceptionGenerator.Program.two() in c:\Users\ADIMA\Documents\Visual Studio
 2013\Projects\ExceptionGenerator\ExceptionGenerator\Program.cs:line 31
   at ExceptionGenerator.Program.one() in c:\Users\ADIMA\Documents\Visual Studio
 2013\Projects\ExceptionGenerator\ExceptionGenerator\Program.cs:line 26
   at ExceptionGenerator.Program.Main(String[] args) in c:\Users\ADIMA\Documents
\Visual Studio 2013\Projects\ExceptionGenerator\ExceptionGenerator\Program.cs:li
ne 15

I want to do fairly the same thing in C++, but I'm not sure about two things...how do you get the file and also the line number you're at?

Example code I have working so far:

// StackTracing.cpp : Defines the entry point for the console application.
//

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

using namespace std;

int LogStackTrace()
{
    void            *stack[100];
    WORD            numberOfFrames;
    SYMBOL_INFO     *symbol;
    HANDLE          process;
    process = GetCurrentProcess();
    SymInitialize(process, NULL, TRUE);
    numberOfFrames = CaptureStackBackTrace(0, 1000, stack, NULL);
    symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO)+256 * sizeof(char), 1); 
    symbol->MaxNameLen = 255;
    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    printf("Caught exception ");
    for (int i = 0; i < numberOfFrames; i++)
    {
        SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
        printf("at %s, address 0x%0X\n", symbol->Name, symbol->Address);
    }
    return 0;
}

void function2()
{
    throw new exception("Expected exception.");
}

void function1()
{
    function2();
}

void function0()
{
    function1();
}

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

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

Output:

Press any key to exit.
Caught exception at LogStackTrace, address 0xB13860
at threadFunction, address 0xB15680
at beginthread, address 0xFCF31E0
at endthread, address 0xFCF33E0
at BaseThreadInitThunk, address 0x7656494F
at RtlInitializeExceptionChain, address 0x772E986A
at RtlInitializeExceptionChain, address 0x772E986A
Alexandru
  • 12,264
  • 17
  • 113
  • 208
  • Looking around in the api for a few minutes will quickly land you on SymGetLineFromAddr() – Hans Passant Mar 17 '14 at 18:40
  • @HansPassant Yeah, but how to allocate and pass in the PIMAGEHLP_LINE struct is tricky to me... – Alexandru Mar 17 '14 at 18:49
  • Plus, what about the file name? – Alexandru Mar 17 '14 at 18:52
  • PIMAGEHLP_LINE contains a LineNumber and FileName, but it still doesn't return proper values for me, and I'm trying to malloc that struct up and have it work :/ its really frustrating – Alexandru Mar 17 '14 at 19:10
  • @HansPassant Challenge: Post a working solution...where calling SymGetLineFromAddr actually works, because I can't get the magic to happen...always returns line 0, and a null filename... – Alexandru Mar 17 '14 at 19:50
  • I can think of a better way to spend my free time. Getting line number info for optimized code is quite useless. And info that's usually stripped from the PDB. You've got enough rep to put a 500 bounty on the question, probably enough to get somebody to write the code for you. – Hans Passant Mar 17 '14 at 19:56
  • @HansPassant Hans, you spend most of your time on here Googling canonical documentation anyways. Countless times you've commented on my questions with canonical citations that got you up-votes. There is a big difference between the applied and theoretical. Why not give your mind a jog instead of your fingers for once? – Alexandru Mar 17 '14 at 19:59
  • Here's the underlying problem, @HansPassant: http://stackoverflow.com/questions/22465253/symgetlinefromaddr-not-working-properly – Alexandru Mar 17 '14 at 21:12

1 Answers1

0

Maybe the stack frame class could help you here.

Markus Safar
  • 6,324
  • 5
  • 28
  • 44