Home » Community » Forums » » General Purpose Call Stack Tracer
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic


 Last Thread Next Thread 
 General Purpose Call Stack Tracer
Post Reply 
Something I forgot to mention, that this thing will DIE (in a horrible, greusome death) if used in any level of recursion.

So basically, if you're not using recursive functions, have a blast

Otherwise, a dynamically allocated solution would be better.

 User Rating: 1168   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

What if you have more than one return point in a function? You'd have to place the macro before all the returns. This could be error prone; what if you forget one.

There could be a macro that call the other macro and returns the specified value, but you'd have to remember not to use the normal return.

A simple object on the stack that calls enter in the constructor and leave in the destructor would be good. I'm sure everyone already thought about that, and I'm not introducing anything new here, but I know it would help.
On the other hand, I can see where it would fail: exceptions. Since C++ is nice and it calls the destructors when an exception is thrown, it would call the destructor of the auto object, rendering the system useless.

So that leaves us with the return macro.

----------------
Blaster
Computer game programmer and part time human being
Strategy First - http://www.strategyfirst.com
BlasterSoft - http://www.blastersoft.com

[edited by - Blaster on October 25, 2002 1:07:58 PM]

 User Rating: 1016   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

What we have is a class and a CALLSTACK macro. The macro declares a static instance of the class. The constructor of the class registers the function name on the callstack. The destructor of the class removes the function name from the callstack. The destructor is automatically called when the object goes out of scope, ie. when you leave the function. So all we need is the following...

void MyFunc(int param)
{
CALLSTACK("MyFunc");

// code
}

 User Rating: 1003   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Sly : yes, that's the kind of "auto" object I was talking about. But as I said, you loose the callstack when an exception is thrown, because the destructors of the auto objects are called.

----------------
Blaster
Computer game programmer and part time human being
Strategy First - http://www.strategyfirst.com
BlasterSoft - http://www.blastersoft.com

 User Rating: 1016   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Why does it die if used in a recursive fashion?

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

why not use __FUNCTION__ instead of a param?

 User Rating: 999   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Is __FUNCTION__ standard C++? I hadn't heard of it before.

[edited by - david_williams on November 21, 2002 6:26:38 PM]

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

My new version uses __FUNCTION__, and uses templates to avoid the inclusion of a .cpp file

Also, it handles exceptions by using the std::uncaught_exception() function in the dtor of the auto_object

It also only requires the use of a single macro at the beginning of the function

 User Rating: 1168   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I got a compile error at callstacktrace.cpp(72) : fatal error C1010.Please help!!!

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
Original post by Yamaha
I got a compile error at callstacktrace.cpp(72) : fatal error C1010.Please help!!!


Yamaha, you'd add both provided source files (callstacktrace.cpp and callstacktrace.h) to your project, and include the callstacktrace.h in your files where you want to use the tracing functionality.

Detailed description is provided with the source (see top section of header file).


 User Rating: 1015    Report this Post to a Moderator | Link

quote:
Original post by daerid
My new version uses __FUNCTION__, and uses templates to avoid the inclusion of a .cpp file

Also, it handles exceptions by using the std::uncaught_exception() function in the dtor of the auto_object

It also only requires the use of a single macro at the beginning of the function


I managed to write my own CallStack tracer class, using stack instead of double linked lists. I also use std::uncaught_exception() in the dtor of the CallStackTrace. There is a problem with VC6, as this function is not correctly implemented - it always returns false...



 User Rating: 1015    Report this Post to a Moderator | Link

quote:
Original post by david_williams
Is __FUNCTION__ standard C++? I hadn't heard of it before.

<SPAN CLASS=editedby>[edited by - david_williams on November 21, 2002 6:26:38 PM]</SPAN>


__FUNCTION__ is not ANSI C++ predefined macro name, so I would not use it. I pass the function name as you did in your original source.



 User Rating: 1015    Report this Post to a Moderator | Link

The macro for tracing the program can easily be changed flow even in recursive-called functions. For example like this:

class CDbgFlowTrace{
static CString m_strCurrentStack;
CString m_strMyContribution;
public:
CDbgFlowTrace(CString strMyContribution)

{
m_strMyContribution=strMyContribution;
m_strCurrentStack +=strMyContribution+";";
//and possibly write m_strCurrentStack into file
};
~CDbgFlowTrace()
{m_strCurrentStack.RemoveEndChars(strMyContribution.GetLength);};
};// CDbgFlowTrace

#define FLOW_TRACE(x) CDbgFlowTrace x(x)

void f1()
{
FLOW_TRACE(ENTERED_f1)
// code
FLOW_TRACE(IN_MIDDLE_OF_f1)
// code2
}


-----------------

It is true that this does not tell me, which dtors were called AFTER the exception has been raised. (My experience says that "interval dividing" enables to find the problem very quickly.)

But I am very sorry than in the Microsoft Visual C++ the uncaught_exception is implemented like {return false;}; Life would be much easier :-)

(A very witty article about this is http://world.std.com/~swmcd/steven/ms/bugs.html.)

----------------------
Pavel
pjel@centrum.cz

 User Rating: 1015    Report this Post to a Moderator | Link

I'll add a small correction - it should be
#define FLOW_TRACE(x) CDbgFlowTrace x(#x);


 User Rating: 1015    Report this Post to a Moderator | Link

If you're only going to use this for debugging purposes then why not use StackWalk API instead?
I guess it could be useful for identifying certain key functions but it still seems like a lot of work to add function calls all over the place when the information can be deduced from the actual call stack.

 User Rating: 1492   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: