identify end of function code at running time

Hello,
I have some question. I want to implement some "debugger like" tool (very limited one, just identify at running time the current stack trace, and print messages from the user) on some code that the user wrote. what I get from the user is a function name (in the beginning of it's declaration), and when the user want to print some message he uses some print macro I should implement.
My target is printing the stack call, and all the messages that the user wrote,
in the right place on the running place.

Does anyone know what c++ feature can help me know on running time that a specific function code has ended??

Its easy to push a function to some vector when it called (since I get its name from the user), but when it ends and return to the function called it...I don't know how to idenfy it, thanks in regards to any helper!!
I'm not quite sure what you're asking - the function ends when program flow returns to your code.
I'll give an example to makes things clearer, let's say my code is:

int main()
{
func_name (function main()) // the user inform that main started
A();
}

void A ()
{
func_name (function A());
user_message (" In A()");
B();
user_message (" In A() after B()");
}

void B ()
{
func_name (function B());
user_message ("In B()");
}

In this case, my output file should be:

main()
{
A()
{
In A();
B()
{
In B();
}
In A() after B()
}
}

So, it's not hard to know that the stack call is main->A->B, but what I dont
know how to do, is when the code of B() ends, know that I'm back in A(), and print the message "In A() after B()", at the right place (plus, print the "}" at the right place. thanks!

Instead of calling functions for that, you should create objects - that way when the functions end the objects get destructed and you can handle that in your destructors.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void A();
void B();

int main()
{
    DebugStackTracer dst ("main()");
    A();
}

void A()
{
    DebugStackTracer dst ("A()");
    dst.note("user message");
    B();
}

void B()
{
    DebugStackTracer dst ("B()");
}
actually they are macros (I just thought it would be easier to write them as functions) so I guess that supports your theory. Can I define an Object using a Macro? thanks again!
Last edited on
#define MyMacro(blah) DebugStackTracer dst (blah)

Why in the world would you want to use macros though? They are deprecated and the creator of C++ wants to remove them from the language (though he can't)
Last edited on
It's not that I want, that was the "demand" I got.. I agree I don't like macros either...:). I'll try to change all my code to this version, and hope it atleast will solve this problem.
By the way, is it OK to use the same name like you did in your example (dst)?
It should be.
Why wouldn't it be OK? I'm not some greedy corporate executive that trademarks and copyrights everything I write so that you have to pay 200% royalties to use what I write.
LOL thanks LB. One more a bit harder thing I would like to hear your advice about. Let's say I'm only want to print until the last function that the user put a message in. If it calls additional function with out a message, I don't want to print their blocks, since it is un relevant. For example, on my previous example, if I remove the line from B, "user_message ("In B()")", the output should be:

main()
{
A()
{
In A();

In A() after B()
}
}

And even if B() was calling to other function, say C, and the user didn't put a message there either, it would still be the right output ( if the user did not put any message in the program the output should be an empty file..).
I thought that in this case I have no choice but define a function for the macro, instead of the object. The problem with this is it go back to my first question...if I use a function, I coudn't declare an object (only one line replaces the Macro!). Do you have any idea how can I solve this problem?
This is the basic idea that LB was suggesting: instantiate a local object at function scope, the constructor and destructor of which will log messages. In a function where such an object is not instantiated, no message will be logged.

This example uses C++11 stuff; __func__ and variadic templates.

Comment out lines 47 and 48, and bar() will produce no log messages. (Because no object will be instantiated)
Comment out lines 54 and 55, and foo() will produce no log messages.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include <string>

struct tracer
{
    explicit tracer( const char* function_name )
          : name(function_name), tab( depth * TABSZ, ' ' )
    { std::clog << tab << depth << ". enter " << name << '\n' ; ++depth ; }

    ~tracer() { --depth ; std::clog << tab << depth << ". exit " << name << '\n' ; }

    template < typename T > tracer& print( const T& v )
    { std::clog << v ; return *this ; }

    template < typename FIRST, typename... REST >
    tracer& print( const FIRST& first, const REST&... rest )
    { print(first) ; return print(rest...) ; }

    template < typename... ARGS > tracer& println( const ARGS&... args )
    {
        std::clog << tab << name << ": " ;
        print(args...) ;
        std::clog << '\n' ;
        return *this ;
    }

    tracer( const tracer& ) = delete ;
    tracer( tracer&& ) = delete ;

    const std::string name ;
    const std::string tab ;

    private: static std::size_t depth ;
    static constexpr std::size_t TABSZ = 4 ;
};

std::size_t tracer::depth = 0 ;

#define TRACE0(identifier) tracer identifier { __func__ }
#define TRACE() TRACE0( local_tracer____ )
#define LOG local_tracer____.println

int foo( int ) ;

int bar( int n )
{
    TRACE() ;
    LOG( "n == ", n ) ;
    return n==0 ? 1 : n - foo( bar(n-1) ) ;
}

int foo( int n )
{
    TRACE() ;
    LOG( "n == ", n ) ;
    return n==0 ? 0 : n - bar( foo(n-1) ) ;
}

int main()
{
    TRACE() ;
    bar(5) ;
}


http://liveworkspace.org/code/3uGVfj$0

Thanks JLBorges, this code looks a bit too hard (and I also don't know c++11, I'm working with VS2008). But for the basic idea, I have 2 macros to implement, this is a given fact and I can't change it.
One with the name of the function (at the beginning of its declaration),
and the other with a message that the user writes.

I think I must create an object (or its instance for that matter) in the first macro. As for the second, I probably need to call a function to set the message, but in this way also objects without a message will be created by the first macro.

By the way, sometimes function with out a message should be printed, in the case the call another function that printf a message (i.e. part of the chain of calls that ends with a function that has a message).

What I was thinking is somehow keeping the objects (or its pointes) in some data base, so I could keep track of whats going on, but its getting a bit messy I think...
Last edited on
> I think I must create an object (or its instance for that matter) in the first macro.
> As for the second, I probably need to call a function to set the message,
> but in this way also objects without a message will be created by the first macro.

The object that is created with the first macro would have a constructor and a destructor; these would print the enter/exit messages anyway.


> By the way, sometimes function with out a message should be printed,
> in the case the call another function that printf a message
> (i.e. part of the chain of calls that ends with a function that has a message).

Even without the creation of a trace object? That is much harder. I don't really know of a reasonable way of doing that with VS2008.
Well you can define it and let the macro call a function that will use it,
I just said that you can't put 2 instructions at a time instead of a macro (i.e. can't create some object and then call some funtion). Anyway, I appreciate your code example and answers!
Topic archived. No new replies allowed.