> "Segmentation fault (core dumped)." Okay, what's segmented and/or faulty?
The OS sees your program as logically separate entities (like code and data), and these are the segments.
A fault is doing something (a memory access) which isn't inside one of the known segments of memory.
> My system has 4 cores. Why you dumping on my cores, dude?
core in this sense of the word refers to core memory (you have to go
back to the 1960's to understand this one).
It's just the memory near to the processor in which your program was running.
The core dump is a file (usually called core) which is a copy of that memory at the point the program crashed.
The idea being you can then use a debugger to do a post-mortem analysis and figure out what went wrong.
Whether you actually get a core file depends on your system admin (read about 'ulimit -c').
The way to practice GDB is start with really simple programs with known obvious faults.
Code:
$ cat foo.c
#include <stdio.h>
void foo ( int *p ) {
*p = 42;
}
int main ( ) {
int p;
foo(&p);
foo(0);
}
$ gcc foo.c
$ ./a.out
Segmentation fault (core dumped)
OK, that didn't work, I wonder why
Compile with debug information, then use gdb
Code:
$ gcc -g foo.c
$ gdb -q ./a.out
Reading symbols from ./a.out...
(gdb) run
Starting program: a.out
Program received signal SIGSEGV, Segmentation fault.
0x0000555555555159 in foo (p=0x0) at foo.c:3
3 *p = 42;
(gdb) bt
#0 0x0000555555555159 in foo (p=0x0) at foo.c:3
#1 0x0000555555555193 in main () at foo.c:8
(gdb) up
#1 0x0000555555555193 in main () at foo.c:8
8 foo(0);
(gdb)
Commands 'bt' (for backtrace) 'up' and 'down' allow you to see how you arrived at this particular state.
A slightly longer example.
Code:
$ gdb -q ./a.out
Reading symbols from ./a.out...
(gdb) b foo
Breakpoint 1 at 0x1149: file foo.c, line 2.
(gdb) run
Starting program: a.out
Breakpoint 1, foo (p=0x5555555551b0 <__libc_csu_init>) at foo.c:2
2 void foo ( int *p ) {
(gdb) n
3 *p = 42;
(gdb)
4 }
(gdb)
main () at foo.c:8
8 foo(0);
(gdb) list
3 *p = 42;
4 }
5 int main ( ) {
6 int p;
7 foo(&p);
8 foo(0);
9 }
(gdb) print p
$1 = 42
(gdb) c
Continuing.
Breakpoint 1, foo (p=0x7fffffffde64) at foo.c:2
2 void foo ( int *p ) {
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x0000555555555159 in foo (p=0x0) at foo.c:3
3 *p = 42;
(gdb) bt
#0 0x0000555555555159 in foo (p=0x0) at foo.c:3
#1 0x0000555555555193 in main () at foo.c:8
(gdb)
Start with a 'b' (breakpoint) on the suspect function, then run the program.
Execute the next line using 'n' (next)
Continue the program using 'c' (continue), which runs the program until the next breakpoint, fault, or normal program exit (whichever comes first).
You can print variables using the 'p' (print) command.
With just those few commands, you can figure out a lot of stuff about how your program is behaving.