views:

155

answers:

6

Plus, The program runs on a arm device running Linux, I can print out stack info and register values in the sig-seg handler I assign. The problem is I can't add -g option to the source file, since the bug may won't reproduce due to performance downgrade.

+1  A: 

This seems to work http://tlug.up.ac.za/wiki/index.php/Obtaining_a_stack_trace_in_C_upon_SIGSEGV

static void signal_segv(int signum, siginfo_t* info, void*ptr) {
// info->si_addr is the illegal address
}
overboming
`info->si_addr` is the faulting memory address. As noted in the link you provided, the address at the time the signal was raised can be retrieved from `void * ptr`. See my answer here for code I have used with ARM - http://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes/1925461#1925461
jschmier
+3  A: 

I tend to use valgrind which indicates leaks and memory access faults.

ereOn
valgrind is for X86, AMD64 and PPC - the questioner is running on ARM. However I am pleasantly surprised to read that ARM support is in progress.
crazyscot
@crazyscot I indeed missed the "arm" part of the question. But nice to know valgrind is about to support this architecture ;)
ereOn
+10  A: 

Compiling with the -g option to gcc does not cause a "performance downgrade". All it does is cause debugging symbols to be included; it does not affect the optimisation or code generation.

If you install your SIGSEGV handler using the sa_sigaction member of the sigaction struct passed to sigaction(), then the si_addr member of the siginfo_t structure passed to your handler contains the faulting address.

caf
I Have had issues where a segfault that was caused by writing to an un-initialized pointer appeared and disappeared depending on whether I used -g, or what -o level I had. It has to do with what memory is where. Similarly, I've had it where adding or deleting a printf made the error appear. segfaults in C can be wily bastards.
Brian Postow
+1  A: 

If you are worried about using -g on the binary that you load on the device, you may be able to use gdbserver on the ARM device with a stripped version of the executable and run arm-gdb on your development machine with the unstripped version of the executable. The stripped version and the unstripped version need to match up to do this, so do this:

# You may add your own optimization flags
arm-gcc -g program.c -o program.debug 
arm-strip --strip-debug program.debug -o program
# or
arm-strip --strip-unneeded program.debug -o program

You'll need to read the gdb and gdbserver documentation to figure out how to use them. It's not that difficult, but it isn't as polished as it could be. Mainly it's very easy to accidentally tell gdb to do something that it ends up thinking you meant to do locally, so it will switch out of remote debugging mode.

nategoose
A: 

You may also want to use the backtrace() function if available, that will provide the call stack at the time of the crash. This can be used in order to dump the stack like it happens in an high level programming language when a C program gets a segmentation fault, bus error, or other memory violation error.

backtrace() is available both on Linux and Mac OS X

antirez
A: 

If the -g option makes the error disappear, then knowing where it crashes is unlikely to be useful anyway. It's probably writing to an uninitialized pointer in function A, and then function B tries to legitimately use that memory, and dies. Memory errors are a pain.

Brian Postow