I am trying to figure out how people use the __LINE__ macro at work. How do you guys use it?
views:
357answers:
8You can use __LINE__, along with __FILE__, to report where problems occur in the source code.
Consider, for example, the assert() macro - this wording from the C99 standard, but C++ is similar, except it does not mention __func__:
When it is executed, if expression (which shall have a scalar type) is false (that is, compares equal to 0), the assert macro writes information about the particular call that failed (including the text of the argument, the name of the source file, the source line number, and the name of the enclosing function — the latter are respectively the values of the preprocessing macros
__FILE__and__LINE__and of the identifier__func__) on the standard error stream in an implementation-defined format.
#define assert(x) (void)(((x)==0)?_Assert(#x,__FILE__,__LINE__,__func__):0)
Just like this:
$ cat line.cc
#include <iostream>
int main(void) {
std::cout << "Hello, world from " << __LINE__ << std::endl;
return 0;
}
$ g++ -o line line.cc
$ ./line
Hello, world from 4
$
if (something truly impossible has happened) {
fprintf(stderr, "Value of PI less than 3 detected at %s line %d\n", __FILE__, __LINE__);
}
It's especially handy in CPP macros that detect intolerable conditions.
I wrote a wrapper for malloc:
#if DEBUG #define malloc(s) debugging_malloc(s, __FILE__, __LINE__) #define free(p) debugging_free(p) // Also, calloc(), strdup(), realloc() should be wrapped. #endif // DEBUG
Within the wrapper, allocations are tracked according to the file and line number at which they occur. When the program exits, a utility functions outputs a list of any unfreed blocks.
If you are using gcc, it also gives you __FUNCTION__, which is really nice. C99-compliant compilers also have __func__, just as handy.
It's really just for debugging/logging purposes. I rarely use it because I tend to rely on debuggers like gdb more often.
But you could always use it when outputting debug information.
void dosomething(Object* o)
{
if (!o) {
std::cerr << __FILE__ << ":" << __LINE__ << ": o is NULL!\n";
abort();
}
}
Just to vaguely quote from the top of my head:
#define assert(e) ((e) ? (void)0 : printf("Assertion failed %s, %s : %s", #e, __FILE__, __LINE__))
An even simpler example, here's a macro I occasionally use when all other forms of debugging have failed:
#define GOT_HERE std::cout << "At " __FILE__ ":" << __LINE__ << std::endl
Then when your code is mysteriously crashing and taking the device down with it, you can at least sprinkle this macro liberally into the source, in the hope that it will let you narrow down where the crash occurs (and after how many repeats). In practice you might not write to std::cout, but rather use the lowest-level, most reliable character output available on the platform.
Most of the answers so far have involved some sort of debugging code. Another use of __LINE__ (and possibly __FILE__) is to enable a macro to generate a unique identifier each time it's called. This implementation of coroutines in C uses these macros to generate labels for a case statement, so it can jump to the last line you called yield from.