This information is tracked by Ubuntu 7.10, GCC 4.1.3, and GDB 6.6-Debian.
When printf is not valid enough ....
1.Read error information
A simple example;
# Include <stdio. h>
# Include <stdlib. h>
Void (){
Char * s = "ee ";
Free (s );
}
Int main (INT argc, char ** argv ){
A ();
Return 1;
}
Run the program and get the following error message:
* ** Glibc detected **./R: Free (): Invalid Pointer: 0x0804865c ***
======= Backtrace: ============
/Lib/tls/i686/cmov/libc. so.6 [0xb7e2dd65]
/Lib/tls/i686/cmov/libc. so.6 (cfree + 0x90) [0xb7e31800]
./R [0x804838c]
./R [0x80483a4]
/Lib/tls/i686/cmov/libc. so.6 (_ libc_start_main + 0xe0) [0xb7dda050]
./R [0x8048311]
======= Memory map: ========
08048000-08049000 R-XP 00000000 1047431/home/Jing/desktop/EE/R
08049000-0804a000 RW-P 00000000 1047431/home/Jing/desktop/EE/R
0804a000-0806b000 RW-P 0804a000 00:00 0 [heap]
B7db8000-b7dc2000 R-XP 00000000 3499334/lib/libgcc_s.so.1
B7dc2000-b7dc3000 RW-P rja000 08:05 3499334/lib/libgcc_s.so.1
B7dc3000-b7dc4000 RW-P b7dc3000 0
B7dc4000-b7f08000 R-XP 00000000 3532035/lib/tls/i686/cmov/libc-2.6.1.so
B7f08000-b7f09000 r -- p 00143000 3532035/lib/tls/i686/cmov/libc-2.6.1.so
B7f09000-b7f0b000 RW-P 00144000 3532035/lib/tls/i686/cmov/libc-2.6.1.so
B7f0b000-b7f0e000 RW-P b7f0b000 0
B7f22000-b7f24000 RW-P b7f22000 0
B7f24000-b7f3e000 R-XP 00000000 3499469/lib/ld-2.6.1.so
B7f3e000-b7f40000 RW-P 00019000 3499469/lib/ld-2.6.1.so
Bff2d000-bff42000 RW-P bff2d000 0 [Stack]
Ffffe000-fffff000 R-XP 00000000 0 [vdso]
Aborted (core dumped)
Backtrace provides function calls.
Memroy map is the virtual memory allocation for program allocation. Its format varies with operating systems. The above information is run in Linux. Actually, the output is/proc/PID/Maps information.
(This figure is not displayed normally in my browser. You can click the memory map connection to view the source)
40049000-4035c000 r-xp 00000000 03:05 824473 /jdk1.5/jre/lib/i386/client/libjvm.so|<------------->| ^ ^ ^ ^ |<----------------------------------->| Memory region | | | | | | | | | | Permission --- + | | | | r: read | | | | w: write | | | | x: execute | | | | p: private | | | | s: share | | | | | | | | File offset ----------+ | | | | | | Major ID and minor ID of -------+ | | the device where the file | | is located (i.e. /dev/hda5) | | | | inode number ------------------------+ | | File name -------------------------------------------------------+
The code segment permission is r-XP and the data segment permission is RW-P.
If you can immediately understand where the error is, if you cannot find the error immediately, you need some skills to quickly find the problem.
2.Find the wrong Function
-Rdynamic option is used for linking programs
gcc -g -o memleak memleak.c -rdynamic -ldl
-rdynamic
Pass the flag -Export-dynamicTo the elf linker, on targets that support it.
This instructs the linker to add all symbols, not only used ones,
To the dynamic symbol table. This option is needed for some uses
dlopen
Or to allow obtaining backtraces from within a program.
-LDL can view man dlopen (I don't quite understand the essence of this dynamic linking .)
Run and report an error. You can get the information of the signed table:
======= Backtrace: ============
/Lib/tls/i686/cmov/libc. so.6 [0xb7dfed65]
/Lib/tls/i686/cmov/libc. so.6 (cfree + 0x90) [0xb7e02800]
./R (A + 0x18) [0x804859c]
./R (main + 0x16) [0x80485b4]
/Lib/tls/i686/cmov/libc. so.6 (_ libc_start_main + 0xe0) [0xb7dab050]
It can be seen from this that the free () call of a () is incorrect.
3. stack traceLocate error to line
If a function is called multiple times, the function name cannot tell which call has a problem. You can try the following method:
- Call GDB for debugging
- Set the breakpoint for the error function, such as B free
- After the breakpoint is reached, run the "BT" command to check the function call status and find out which function is called until an error is found.
* It is very troublesome to check every function and capture the system's error signal,
# Include <stdio. h>
# Include <stdlib. h>
# Include <string. h>
# Include <signal. h>
Void ()...{
Char * s = "33 ";
Char * D = NULL;
Strcpy (D, S );
Free (s );
Return;
}
Void sighandler ()...{
}
Int main (INT argc, char ** argv )...{
Signal (SIGSEGV, sighandler );
A ();
Return 1;
}
During debugging, B sighandler and then BT.
However, capturing SIGSEGV is dangerous. You cannot capture it infinitely. Otherwise, the loop is infinite. One capture is enough.
5. orGDBNext, try it after the program is forcibly exited.LIST Command
6. Tools:Valgrind
There are many memory error tools, valgrind is the most powerful one. Some tools provide a library to connect to the source code. It is inconvenient to change it back after it is finished.
Some tools check some specific calls:
* Strace: System Call, such as opening or closing a file
* Mtrace, electronice fence (GRID), dmalloc, memwatch (mastering Linux Debugging techniques): malloc call
* Ltrace: "dynamic library call"
* NM, objdump: OBJ file information, which is too cumbersome and may not be used. These two tools have never been used.
7.Others
Smash the stack
GCC and OBJ files, dynamic link files, and elf files