0

Assume I have a class definition like this:

class A {
    void method();
}

Assume I need to find where this method is called directly from C++ (i.e gdb and company are rulled out, so is throwing an exception)

One could naively define the following:

class A {
    //void method();
    void method() { print(__FILE__ + ": " + __LINE__) };
}

This will however print the file and line of the current method, not the file and line of where the method is called.

If instead of OOP our code was procedural once could convert:

void method();

To:

#define method() { print(__FILE__ + ": " + __LINE__) };

The above works because method takes in no parameters, so it;s easy for the peprocessor to change all instances of the method to our new debugging code.

However this is not very general. With OOP we can have classes A, B, C and D all overwriting the method, thus overprinting information for unrelated classes.

Even if only class A implements method() if the function takes any parameters, now we get a new issue: method(int i) would require a regular expression to be replaced since we have no prior knowledge of the variable names bassed into the method. i.e the pattern a.method(variable); cannot be statically matched by a constant define, we would need to match regular expressions.

Does anyone know if it is possible to trick the compiler into resolving the __FILE__ and __LINE__ macros at the call rather than the definition?

EDIT:

The question marked as duplicate is from 2010, I think it's worth keeping this one open, 9 years seems more than enough time for new potential answers to be given to this question.

for example std::experimental::source_location doesn't appear in the question.

I would like this question to be reopened

Makogan
  • 8,208
  • 7
  • 44
  • 112
  • 2
    Providing call site information (line and file) is not doable with any C++ technique I know of but preprocessor. This is a reason why there is a macro at the heart of many logging frameworks I worked with. What you could do is to take the method accept file and line as variables and print them, and call this method through invocation macro. – SergeyA May 15 '19 at 19:43
  • 2
    No standard feature allows this. Your best bet is to capture the information at the call site. Callstack introspection is not easy in C++. – François Andrieux May 15 '19 at 19:46
  • The logging framework I have to work with daily takes file/line number as first two arguments of every log function call. So all calls look like `log_debug(__FILE__, __LINE__, "message");`. Not great, but it does the job.. – Jesper Juhl May 15 '19 at 19:48
  • 1
    You might be interested in the proposed [`std::experimental::source_location`](https://en.cppreference.com/w/cpp/experimental/source_location). – Deduplicator May 15 '19 at 19:51
  • 1
    @πάντα: A full stacktrace is far more than asked for. Anyway, `source_location` might become an interesting new alternative. – Deduplicator May 15 '19 at 19:55

1 Answers1

2

If you're using GCC, this has been available from GCC 4.8:

#include <cstdio>

struct Foo
{
    void debug(const char *file=__builtin_FILE(), int line=__builtin_LINE(), const char *function=__builtin_FUNCTION())
    {
        printf("%s:%d: called from %s\n", file, line, function);
    }
};

int main()
{
    Foo().debug();
}
o11c
  • 15,265
  • 4
  • 50
  • 75