Http://blog.163.com/lanka83/blog/static/32637615200801793020182/
Http://blog.csdn.net/taina2008/archive/2007/08/09/1733464.aspx
1. Preface:
Some programs can be compiled, but segment fault (segment error) may occur during runtime. This is usually caused by pointer errors.
However, this does not prompt the file-> line like a compilation error, but does not have any information, making debugging difficult.
Before using core debugging, make sure that the core file size is set to non-0. You can only use ulimit-a to check that the first item is the core file size. If it is 0
You must modify the file size. I set the file size as follows: ulimit-C unlimited. The core file size is not limited. In this way, the system can produce core files.
2. GDB:
One way is to use GDB step for further search.
It is feasible to put it in short code, but to let you step into a code of tens of thousands of lines, I think you will hate the programmer name and call it a programmer.
We still have a better solution, which is core file.
3. ulimit:
If you want the system to generate a core file when an error occurs due to signal interruption, you need to set it in shell as follows:
# Set the core size to unlimited
Ulimit-C Unlimited
# Set the file size to unlimited
Ulimit Unlimited
These require the root permission. In ubuntu, you need to re-enter the first command to set the core size to infinite.
4. Use GDB to view the core file:
Here we can dump the core when an error occurs due to the message number.
After a core dump occurs, use GDB to view the content of the core file to locate the line that causes the core dump in the file.
GDB [exec file] [core file]
For example:
GDB./test. Core
After entering GDB, run the BT command to check where the program is running and locate the core dump file-> line.
5. Use GDB to observe the crash information of a process in real time
Start Process
GDB-P PID
C
Run the process to crash
GDB displays the crash information.
BT
In short, a segment error occurs when you access the wrong memory segment. Generally, you do not have the permission or the corresponding physical memory exists, especially when you access the 0 address.
Generally, a segment error means that the accessed memory exceeds the memory space of the program provided by the system. Generally, this value is saved by GDTR, which is a 48-bit register, the 32-bit table stores the gdt table pointed to by it, and the last 13 BITs are saved to the corresponding gdt subscript, the last three digits include whether the program is in the memory and the running level of the program in the CPU. The gdt pointing to is a table in 64 bits, this table stores the code segment for running the program, the starting address of the data segment, the corresponding segment limit and page switch, the program running level, and the memory granularity. Once a program is accessed out of bounds, the CPU will generate corresponding exception protection, so Segmentation
Fault appears.
In programming, the following methods may easily cause segment errors, which are basically caused by incorrect pointer usage.
1) access the system data zone, especially writing data to the memory address protected by the System
The most common is to give a pointer A 0 address
2) memory out of bounds (array out of bounds, variable types inconsistent, etc.) access to areas not in your memory
Solution
When we write programs in C/C ++, most of the work of memory management needs to be done. In fact, memory management is a tedious task. No matter how clever and experienced you are, it is inevitable that you will make some small errors here. These errors are usually so simple and easy to eliminate. However, manual debugging is often inefficient and annoying, this article will talk about how to quickly locate these "segment errors" statements about memory access out-of-bounds errors.
The following describes several debugging methods for a program with a segment error:
1 dummy_function (void)
2 {
3 unsigned char * PTR = 0x00;
4 * PTR = 0x00;
5}
6
7 int main (void)
8 {
9 dummy_function ();
10
11 return 0;
12}
As a skilled C/C ++ programmer, the bug of the above Code should be very clear, because it tries to operate on the memory area with the address 0, this memory area is usually inaccessible, and of course there will be errors. Let's compile and run it:
Xiaosuo @ gentux test $./A. Out
Segment Error
As expected, it went wrong and exited.
1. Use GDB to gradually find the segment error:
This method is also widely known and widely used. First, we need an executable program with debugging information. Therefore, we add the "-g-rdynamic" parameter to compile the program, use GDB to debug and run the newly compiled program. The specific steps are as follows:
Xiaosuo @ gentux test $ gcc-g-rdynamic d. c
Xiaosuo @ gentux test $ GDB./A. Out
Gnu gdb 6.5
Copyright (c) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
Welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"... using host libthread_db library "/lib/libthread_db.so.1 ".
(GDB) r
Starting program:/home/xiaosuo/test/a. Out
Program received signal SIGSEGV, segmentation fault.
0x08048524 in dummy_function () at D. C: 4
4 * PTR = 0x00;
(GDB)
Oh ?! It seems that we did not need to debug step by step to find the Error Path line 4th of the D. c file, which is actually so simple.
We also found that the process ended with the SIGSEGV signal. After further reading the document (MAN 7 signal), we know that the default handler action of SIGSEGV is to print the error message of "segment error" and generate a core file, therefore, method 2 is generated.
2. Analyze the core file:
What is a core file?
The default action of certain signals is to cause a process to terminate and produce a core dump file, a disk file containing an image of the process's memory at the time of termination. A list of the signals which cause a process
To dump core can be found in signal (7 ).
This document is taken from man page (MAN 5 core ). But it's strange that the core file is not found on my system. Later, I recalled that in order to gradually reduce the number of pull files on the system (I am somewhat clean, which is one of the reasons I like Gentoo), and disabled the generation of core files, check that the following is true, limit the size of the system core file to kb, and try again:
Xiaosuo @ gentux test $ ulimit-C
0
Xiaosuo @ gentux test $ ulimit-C 1000
Xiaosuo @ gentux test $ ulimit-C
1000
Xiaosuo @ gentux test $./A. Out
Segment error (core dumped)
Xiaosuo @ gentux test $ ls
A. out core D. c f. c g. C pango. c test_iconv.c test_regex.c
The core file is finally generated. Use GDB to debug it:
Xiaosuo @ gentux test $ GDB./A. out core
Gnu gdb 6.5
Copyright (c) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
Welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"... using host libthread_db library "/lib/libthread_db.so.1 ".
Warning: Can't read pathname for load map: input/output error.
Reading symbols from/lib/libc. so.6...... done.
Loaded symbols for/lib/libc. so.6
Reading symbols from/lib/ld-linux.so.2... done.
Loaded symbols for/lib/ld-linux.so.2
Core was generated by './A. out '.
Program terminated with signal 11, segmentation fault.
#0 0x08048524 in dummy_function () at D. C: 4
4 * PTR = 0x00;
Wow, it's a good experience. I just got to the wrong location and admire the design of Linux/Unix systems.
Next, when I used Internet Explorer in windows, sometimes some web pages may encounter "runtime errors ", at this time, if a Windows compiler is installed on your machine, a dialog box will pop up asking you if you want to debug it. If you choose yes, the compiler will be opened, and enter the debugging status to start debugging.
How can we achieve this in Linux? My brain is spinning at a high speed. Now, let it call GDB in the handler of SIGSEGV, so the third method is born again:
3. Start debugging when a segment error occurs:
# Include <stdio. h>
# Include <stdlib. h>
# Include <signal. h>
# Include <string. h>
Void dump (INT signo)
{
Char Buf [1024];
Char cmd [1024];
File * FH;
Snprintf (BUF, sizeof (BUF), "/proc/% d/define line", getpid ());
If (! (FH = fopen (BUF, "R ")))
Exit (0 );
If (! Fgets (BUF, sizeof (BUF), FH ))
Exit (0 );
Fclose (FH );
If (BUF [strlen (BUF)-1] = '\ n ')
Buf [strlen (BUF)-1] = '\ 0 ';
Snprintf (CMD, sizeof (CMD), "GDB % S % d", Buf, getpid ());
System (CMD );
Exit (0 );
}
Void
Dummy_function (void)
{
Unsigned char * PTR = 0x00;
* PTR = 0x00;
}
Int
Main (void)
{
Signal (SIGSEGV, & dump );
Dummy_function ();
Return 0;
}
The compilation and running effect is as follows:
Xiaosuo @ gentux test $ gcc-g-rdynamic F. C
Xiaosuo @ gentux test $./A. Out
Gnu gdb 6.5
Copyright (c) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
Welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"... using host libthread_db library "/lib/libthread_db.so.1 ".
Attaching to program:/home/xiaosuo/test/a. Out, process 9563
Reading symbols from/lib/libc. so.6...... done.
Loaded symbols for/lib/libc. so.6
Reading symbols from/lib/ld-linux.so.2... done.
Loaded symbols for/lib/ld-linux.so.2
0xffffe410 in _ kernel_vsyscall ()
(GDB) BT
#0 0xffffe410 in _ kernel_vsyscall ()
#1 0xb7ee4b53 in waitpid () from/lib/libc. so.6
#2 0xb7e925c9 in strtold_l () from/lib/libc. so.6
#3 0x08048830 in dump (signo = 11) at F. C: 22
#4 <signal handler called>
#5 0x0804884c in dummy_function () at F. C: 31
#6 0x08048886 in main () at F. C: 38
How is it? Is it still cool?
The above method is implemented on the premise that GDB is available on the system. If not, what? Actually, glibc provides us with such function clusters that can dump stack content. For details, see/usr/include/execinfo. H (no man page is provided for these functions, so we can't find them). You can also learn from the GNU manual.
4. Use backtrace and objdump for analysis:
The rewrite code is as follows:
# Include <execinfo. h>
# Include <stdio. h>
# Include <stdlib. h>
# Include <signal. h>
/* A dummy function to make the backtrace more interesting .*/
Void
Dummy_function (void)
{
Unsigned char * PTR = 0x00;
* PTR = 0x00;
}
Void dump (INT signo)
{
Void * array [10];
Size_t size;
Char ** strings;
Size_t I;
Size = backtrace (array, 10 );
Strings = backtrace_symbols (array, size );
Printf ("obtained % ZD stack frames. \ n", size );
For (I = 0; I <size; I ++)
Printf ("% s \ n", strings [I]);
Free (strings );
Exit (0 );
}
Int
Main (void)
{
Signal (SIGSEGV, & dump );
Dummy_function ();
Return 0;
}
The compilation and running results are as follows:
Xiaosuo @ gentux test $ gcc-g-rdynamic G. C
Xiaosuo @ gentux test $./A. Out
Obtained 5 stack frames.
./A. Out (dump + 0x19) [0x80486c2]
[0xffffe420]
./A. Out (main + 0x35) [0x802136f]
/Lib/libc. so.6 (_ libc_start_main + 0xe6) [0xb7e02866]
./A. out [0x8048601]
This time you may be disappointed. It seems that you have not provided enough information to mark the error. Don't worry. First, let's take a look at what can be analyzed. Use the objdump disassembly program to find the code location corresponding to address 0x801166f:
Xiaosuo @ gentux test $ objdump-d a. Out
8048765: E8 02 Fe FF call 804856c <signal @ PLT>
80100006a: E8 25 FF call 8048694 <dummy_function>
80100006f: B8 00 00 00 mov $0x0, % eax
8048774: C9 leave
We still found the function (dummy_function) in which the error occurred. The information is not complete, but it is always better!