tags:

views:

357

answers:

8

I am trying to figure out how people use the __LINE__ macro at work. How do you guys use it?

+14  A: 

You 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)
Jonathan Leffler
Specifically a very common use is to write ASSERT() macros which report where they occur as well as what went wrong.
Aaron
Yes, Aaron - I was typing that up as you added the comment!
Jonathan Leffler
+1  A: 

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
$
Dirk Eddelbuettel
A: 
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.

bmargulies
+4  A: 

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.

Heath Hunnicutt
A: 

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();
  }
}
Charles Salvia
A: 

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__))
3yE
Since `printf()` returns an integer, you need to move the void cast so that the overall expression always returns `void`.
Jonathan Leffler
+3  A: 

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.

Steve Jessop
+2  A: 

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.

jleedev