Determine the Line of Code That Causes a Segmentation Fault

Determine the line of code that causes a segmentation fault?

GCC can't do that but GDB (a debugger) sure can. Compile you program using the -g switch, like this:

gcc program.c -g

Then use gdb:

$ gdb ./a.out
(gdb) run
<segfault happens here>
(gdb) backtrace
<offending code is shown here>

Here is a nice tutorial to get you started with GDB.

Where the segfault occurs is generally only a clue as to where "the mistake which causes" it is in the code. The given location is not necessarily where the problem resides.

How to find the line caused segmentation fault in c++ compiled program

When compiling the program, add the -g compiler flag, or even better -ggdb3, which will give you a much prettier output, by adding debugging symbols to the executable. Also, make sure that you compile with the -O0 optimization level.

To actually debug the program, run gdb ./main.out to start the program in a debugging session. If you then run r, gdb will start executing the program, and then stop at the line that gives the segfault.

To figure out how you got to that point, run bt while in the debugging session, and you will get a backtrace, which will show you all the function calls that were made to get to the line of code that crashed.

You can of course do a lot more than this (and you will probably need to, since locating the source of an error is often only the first step). You can use p to print the values of variables, set watchpoints, and many more things. For a while now, gdb even ships with a full fledged python interpreter, so you can even write a python script for your custom debugging needs.

Learning how to use gdb can seem overwhelming at the start, but persevere, and I guarantee the effort will pay off big time :)

Segmentation Fault before even the first line of `main()` is executed and there are no non-local variables

This is definitely a stack overflow. sizeof(dynamic_loop_functor_t) is nearly 64 MiB, and the default stack size limit on most Linux distributions is only 8 MiB. So the crash is not surprising.

The remaining question is, why does the debugger identify the crash as coming from inside std::operator<<? The actual segfault results from the CPU exception raised by the first instruction to access to an address beyond the stack limit. The debugger only gets the address of the faulting instruction, and has to use the debug information provided by the compiler to associate this with a particular line of source code.

The results of this process are not always intuitive. There is not always a clear correspondence between instructions and source lines, especially when the optimizer may reorder instructions or combine code coming from different lines. Also, there are many cases where a bug or problem with one source line can cause a fault in another section of code that is otherwise innocent. So the source line shown by the debugger should always be taken with a grain of salt.

In this case, what happened is as follows.

  • The compiler determines the total amount of stack space to be needed by all local variables, and allocates it by subtracting this number from the stack pointer at the very beginning of the function, in the prologue. This is more efficient than doing a separate allocation for each local variable at the point of its declaration. (Note that constructors, if any, are not called until the point in the code where the variable's declaration actually appears.)

    The prologue code is typically not associated with any particular line of source code, or maybe with the line containing the function's opening {. But in any case, subtracting from the stack pointer is a pure register operation; it does not access memory and therefore cannot cause a segfault by itself. Nonetheless, the stack pointer is now pointing outside the area mapped for the stack, so the next attempt to access memory near the stack pointer will segfault.

  • The next few instructions of main execute the cout << "Starting main". This is conceptually a call to the overloaded operator<< from the standard library; but in GCC's libstdc++, the operator<< is a very short function that simply calls an internal helper function named __ostream_insert. Since it is so short, the compiler decides to inline operator<< into main, and so main actually contains a call to __ostream_insert. This is the instruction that faults: the x86 call instruction pushes a return address to the stack, and the stack pointer, as noted, is out of bounds.

    Now the instructions that set up arguments and call __ostream_insert are marked by the debug info as corresponding to the source of operator<<, in the <ostream> header file - even though those instructions have been inlined into main. Hence your debugger shows the crash as having occurred "inside" operator<<.

    Had the compiler not inlined operator<< (e.g. if you compile without optimization), then main would have contained an actual call to operator<<, and this call is what would have crashed. In that case the traceback would have pointed to the cout << "Starting main" line in main itself - misleading in a different way.


Note that you can have GCC warn you about functions that use a large amount of stack with the options -Wstack-usage=NNN or -Wframe-larger-than=NNN. These are not enabled by -Wall, but could be useful to add to your build, especially if you expect to use large local objects. Specifying either of them, with a reasonable number for NNN (say 4000000), I get a warning on your main function.

SEGMENTATION FAULT for my code , need guidance with debugging

Seem very likely to me that this code

    if(i>0)
{
x+="U";
rat(m,n,ans,i-1,j);
}
x.pop_back();

should be

    if(i>0)
{
x+="U";
rat(m,n,ans,i-1,j);
x.pop_back();
}

Same error several times.

The way you have written it, you will remove characters from x that were never put there in the first place.

Is segmentation fault caused from fopen line a stack overflow problem in C? (darknet, detector.c)

fopen returns a file handle. Just a couple lines above you're defining a variable FILE *log_csv; which would be probably where you want to put that handle.

Furthermore the second argument of fopen is a C-string (i.e. a pointer to a NUL terminated array of chars). TTBT, I'm surprised your compiler did let this pass.

Try this:

FILE *log_csv = fopen("/home/aicar/darknet/0_log_ju0.csv", "a");
if( !log_csv ){
printf("failed to open csv file\n\n");
exit(1);
} else {
printf("%d\n", fileno(log_csv));

}


Related Topics



Leave a reply



Submit