Recently in the Linux environment to do C language project, because it is in an original project on the basis of two development, and the project is huge and complex, there are many problems, one of the most encountered, the most time-consuming problem is the famous "paragraph error" (segmentation Fault). Take this opportunity system to learn a bit, here on the Linux environment section of the error to make a summary, convenient for similar problems after the investigation and resolution.
1. What is a paragraph error?
In a word, a segment error means that the memory accessed exceeds the memory space that the system has set for the program, such as accessing a non-existent memory address, accessing a system-protected memory address, accessing a read-only memory address, and so on. Here is a precise definition of "segment error" (Reference answers.com):
A segmentation fault (often shortened to segfault) are a particular error condition that can occur during the operation of Computer software. In short, a segmentation fault occurs where a program attempts to access a memory location so it is not allowed to access , or attempts to access a memory location in a way this is isn't allowed (e.g., attempts to write to a read-only location, O R to overwrite part of the operating system). Systems based on processors like the Motorola 68000 tend to refer to this events as address or bus errors.
Segmentation is one approach to memory management and protection in the operating system. It has been superseded by paging for most purposes, but much of the terminology to segmentation is still used, "Segmentati On fault ' being an example. Some operating systems still have segmentation at Some logical level although paging is used as the main memory management Policy.
On Unix-like operating systems, a process that accesses invalid memory receives the SIGSEGV signal. On Microsoft Windows, a process that accesses invalid memory receives the status_access_violation exception.
2. Causes of paragraph errors
2.1 Access to Non-existent memory addresses
Copy Code code as follows:
#include <stdio.h>
#include <stdlib.h>
void Main ()
{
int *ptr = NULL;
*ptr = 0;
}
2.2 Access to system-protected memory addresses
Copy Code code as follows:
#include <stdio.h>
#include <stdlib.h>
void Main ()
{
int *ptr = (int *) 0;
*ptr = 100;
}
2.3 Access to read-only memory addresses
Copy Code code as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void Main ()
{
Char *ptr = "Test";
strcpy (PTR, "TEST");
}
2.4 Stack Overflow
Copy Code code as follows:
#include <stdio.h>
#include <stdlib.h>
void Main ()
{
Main ();
}
and other reasons.
3. Access to paragraph error information
When a program has a segment error, the message is very small, and there are several ways to view the occurrence of a segment error.
3.1 DMESG
DMESG can display relevant information stored in the kernel when the application crash out. As shown below, the DMESG command allows you to view the name of the program where a segment error occurred, the memory address that caused the segment error, the instruction pointer address, the stack pointer address, the error code, the cause of the error, and so on. Take program 2.3 For example:
panfeng@ubuntu:~/segfault$ DMESG
[2329.479037] segfault3[2700]: segfault at 80484e0 IP 00d2906a SP bfbbec3c error 7 in libc-2.10.1.so[cb4000+13e000]
3.2-g
When you use GCC to compile the source code for your program, add the-G parameter, which enables you to add useful information that can be used for GDB debugging in the resulting binaries. Take program 2.3 For example:
panfeng@ubuntu:~/segfault$ gcc-g-o segfault3 segfault3.c
3.3 nm
Use the NM command to list symbol tables in a binary file, including symbolic addresses, symbol types, symbol names, and so on, to help locate where a segment error occurred. Take program 2.3 For example:
Copy Code code as follows:
panfeng@ubuntu:~/segfault$ nm SEGFAULT3
08049f20 D _dynamic
08049ff4 D _global_offset_table_
080484DC R _io_stdin_used
W _jv_registerclasses
08049F10 D __ctor_end__
08049f0c D __ctor_list__
08049f18 D __dtor_end__
08049f14 D __dtor_list__
080484EC R __frame_end__
08049f1c D __jcr_end__
08049f1c D __jcr_list__
0804a014 A __bss_start
0804a00c D __data_start
08048490 T __do_global_ctors_aux
08048360 T __do_global_dtors_aux
0804a010 D __dso_handle
W __gmon_start__
0804848a T __I686.GET_PC_THUNK.BX
08049f0c D __init_array_end
08049f0c D __init_array_start
08048420 T __libc_csu_fini
08048430 T __libc_csu_init
U __libc_start_main@ @GLIBC_2.0
0804a014 A _edata
0804a01c A _end
080484BC T _fini
080484d8 R _FP_HW
080482BC T _init
08048330 T _start
0804a014 b completed.6990
0804a00c W Data_start
0804a018 b dtor_idx.6992
080483C0 T Frame_dummy
080483e4 T Main
U memcpy@ @GLIBC_2.0
3.4 LDD
Use the LDD command to view the shared-link library dependencies of a binary, including the name of the library, the starting address, to determine whether a segment error occurred in its own program or in a shared library that is dependent on it. Take program 2.3 For example:
Copy Code code as follows:
panfeng@ubuntu:~/segfault$ LDD./segfault3
Linux-gate.so.1 => (0x00e08000)
Libc.so.6 =>/lib/tls/i686/cmov/libc.so.6 (0x00675000)
/lib/ld-linux.so.2 (0x00482000)
4. Debugging method of Segment error
4.1 Using printf Output information
This is seemingly the simplest but often very effective debugging methods, may be said to be the most used by programmers debugging methods. To put it simply, you add an output such as printf around the important code of your program so that you can track and print out where the errors might appear in your code.
To facilitate this approach, you can use conditional compilation Directives #ifdef Debug and #endif to wrap printf functions. This allows you to view debugging information if you add the-ddebug parameter when the program compiles, otherwise the debug information will not be displayed without this parameter.
4.2 Using GCC and GDB
4.2.1 Debugging steps
1, in order to be able to use the GDB debugger, in the compile phase with the-G parameter, to program 2.3 For example:
panfeng@ubuntu:~/segfault$ gcc-g-o segfault3 segfault3.c
2. Use the GDB command to debug the program:
Copy Code code as follows:
panfeng@ubuntu:~/segfault$ gdb./segfault3
GNU gdb (GDB) 7.0-ubuntu
Copyright (C) 2009 Free Software Foundation, Inc.
License gplv3+: GNU GPL version 3 or later This is the free software:you are and redistribute it.
There is NO WARRANTY and to the extent permitted by. Type "Show copying"
and "Show warranty" for details.
This is GDB was configured as "I486-linux-gnu".
For bugs reporting instructions, please:
Reading symbols From/home/panfeng/segfault/segfault3...done.
(GDB)
3, after entering GDB, run the program:
Copy Code code as follows:
(GDB) Run
Starting program:/HOME/PANFENG/SEGFAULT/SEGFAULT3
Program received signal SIGSEGV, segmentation fault.
0x001a306a in memcpy () from/lib/tls/i686/cmov/libc.so.6
(GDB)
From the output, the program 2.3 received the SIGSEGV signal, triggering a segment error, and prompted the address 0x001a306a, call memcpy reported the wrong, located in the/lib/tls/i686/cmov/libc.so.6 library.
4, after debugging, enter the QUIT command to exit GDB:
Copy Code code as follows:
(GDB) quit
A debugging session is active.
Inferior 1 [process 3207] 'll be killed.
Quit anyway? (Y or N) y
4.2.2 Applicable scene
1, only if you can determine that the program will certainly occur in the case of errors in the use.
2, when the source of the program can be obtained, using the-G parameter compiler program.
3, generally used in the testing phase, the production environment gdb will have side effects: so that the program running slow, not stable, and so on.
4, even in the test phase, if the program is too complex, GDB can not handle.
4.3 using core files and GDB
In section 4.2, the reference to a segment error triggers the SIGSEGV signal, which, through Man 7 signal, can be seen SIGSEGV the default handler will print a segment error error message and produce a core file, whereby we can use debug information from the core file generated when the program exits unexpectedly. , use the GDB tool to debug segment errors in your program.
4.3.1 Debugging steps
1, in some Linux version, the default is not generated core files, you can first look at the system core file size limits:
panfeng@ubuntu:~/segfault$ ulimit-c
0
2, you can see the default settings, the local Linux environment occurs when a segment error does not automatically generate core files, the following set the size of the core file (KB):
panfeng@ubuntu:~/segfault$ ulimit-c 1024
panfeng@ubuntu:~/segfault$ ulimit-c
1024
3, run the program 2.3, the occurrence of a segment error generated core files:
panfeng@ubuntu:~/segfault$./SEGFAULT3
Segment error (Core dumped)
4, loading core files, using the GDB tool for debugging:
Copy Code code as follows:
panfeng@ubuntu:~/segfault$ gdb./segfault3./core
GNU gdb (GDB) 7.0-ubuntu
Copyright (C) 2009 Free Software Foundation, Inc.
License gplv3+: GNU GPL version 3 or later This is the free software:you are and redistribute it.
There is NO WARRANTY and to the extent permitted by. Type "Show copying"
and "Show warranty" for details.
This is GDB was configured as "I486-linux-gnu".
For bugs reporting instructions, please:
Reading symbols From/home/panfeng/segfault/segfault3...done.
Warning:can ' t read pathname for LOAD map: input/Output error.
Reading symbols from/lib/tls/i686/cmov/libc.so.6 ... (No debugging symbols found) ... done.
Loaded symbols for/lib/tls/i686/cmov/libc.so.6
Reading symbols from/lib/ld-linux.so.2 ... (No debugging symbols found) ... done.
Loaded symbols for/lib/ld-linux.so.2
Core is generated by './segfault3 '.
Program terminated with signal, segmentation fault.
#0 0x0018506a in memcpy () from/lib/tls/i686/cmov/libc.6
See from the output, the same segment error message as in 4.2.1.
5, after debugging, enter the QUIT command to exit GDB:
(GDB) quit
4.3.2 Applicable scene
1, suitable for the actual build environment in the debugging process of the error section (that is, without the recurrence of errors in the case of the recurrence section error).
2, when the program is very complex, the core file is quite large, this method is not available.
4.4 Using Objdump
4.4.1 Debugging steps
1, using the DMESG command to find the most recent segment error output information:
panfeng@ubuntu:~/segfault$ DMESG
... ...
[17257.502808] segfault3[3320]: segfault at 80484e0 IP 0018506a SP bfc1cd6c error 7 in libc-2.10.1.so[110000+13e000]
One of the things that is useful for our next debugging process is the address of the segment error: 80484E0 and the instruction pointer address: 0018506a.
2, using Objdump to generate binary information, redirect to the file:
panfeng@ubuntu:~/segfault$ objdump-d./segfault3 > Segfault3dump
The resulting Segfault3dump file contains the SEGFAULT3 assembly code of the binary file.
3, in the Segfault3dump file to find a segment error address:
Copy Code code as follows:
panfeng@ubuntu:~/segfault$ grep-n-A 10-b "80484e0"./segfault3dump
121-80483DF:FF D0 Call *%eax
122-80483e1:c9 leave
123-80483E2:C3 ret
124-80483e3:90 NOP
125-
126-080483e4 <main>:
127-80483E4:55 Push%EBP
128-80483e5:89 e5 mov%esp,%ebp
129-80483e7:83 e4 F0 and $0xfffffff0,%esp
130-80483ea:83 EC Sub $0x20,%esp
131:80483ED:C7 1c E0 MOVL $0x80484e0,0x1c (%ESP)
132-80483f4:08
133-80483F5:B8 e5 mov $0x80484e5,%eax
134-80483fa:c7 movl $0x5,0x8 (%ESP)
135-8048401:00
136-8048402:89 mov%eax,0x4 (%ESP)
137-8048406:8B 1c MOV 0x1c (%ESP),%eax
138-804840A:89 mov%eax, (%ESP)
139-804840d:e8 0a FF FF call 804831c <memcpy@plt>
140-8048412:c9 leave
141-8048413:C3 ret
Through the above assembly code analysis, learned that the section error occurred main function, the corresponding assembly instruction is MOVL $0x80484e0,0x1c (%ESP), then open the program's source code, find the assembly instructions corresponding to the source code, also locate to paragraph error.
4.4.2 Applicable scene
1, do not need A-g parameter compilation, do not need to use the core file, but need to have a certain assembly language base.
2, if the use of GCC compiler optimization parameters (-O1,-O2,-O3), the resulting assembly instructions will be optimized, making the debugging process somewhat difficult.
4.5 Using CATCHSEGV
The CATCHSEGV command is specifically designed to capture a segment error, which is loaded on a written library (/lib/libsegfault.so) by the preload mechanism (preload) of the dynamic Loader (ld-linux.so) to catch error messages for the fault.
Copy Code code as follows:
panfeng@ubuntu:~/segfault$ CATCHSEGV./segfault3
Segmentation fault (core dumped)
Segmentation fault
Register Dump:
eax:00000000 Ebx:00fb3ff4 ecx:00000002 edx:00000000
Esi:080484e5 edi:080484e0 ebp:bfb7ad38 esp:bfb7ad0c
eip:00ee806a eflags:00010203
cs:0073 ds:007b es:007b fs:0000 gs:0033 ss:007b
trap:0000000e error:00000007 oldmask:00000000
ESP/SIGNAL:BFB7AD0C CR2:080484E0
BackTrace:
/LIB/LIBSEGFAULT.SO[0X3B606F]
??: 0 (??) [0xc76400]
/lib/tls/i686/cmov/libc.so.6 (__libc_start_main+0xe6) [0xe89b56]
/build/buildd/eglibc-2.10.1/csu/.. /sysdeps/i386/elf/start. s:122 (_start) [0x8048351]
Memory Map:
00258000-00273000 R-xp 00000000 08:01 157/lib/ld-2.10.1.so
00273000-00274000 r--p 0001a000 08:01 157/lib/ld-2.10.1.so
00274000-00275000 rw-p 0001b000 08:01 157/lib/ld-2.10.1.so
003b4000-003b7000 R-xp 00000000 08:01 13105/lib/libsegfault.so
003b7000-003b8000 r--p 00002000 08:01 13105/lib/libsegfault.so
003b8000-003b9000 rw-p 00003000 08:01 13105/lib/libsegfault.so
00c76000-00c77000 R-xp 00000000 00:00 0 [VDSO]
00e0d000-00e29000 R-xp 00000000 08:01 4817/lib/libgcc_s.so.1
00e29000-00e2a000 r--p 0001b000 08:01 4817/lib/libgcc_s.so.1
00e2a000-00e2b000 rw-p 0001c000 08:01 4817/lib/libgcc_s.so.1
00e73000-00fb1000 R-xp 00000000 08:01 1800/lib/tls/i686/cmov/libc-2.10.1.so
00fb1000-00fb2000---p 0013e000 08:01 1800/lib/tls/i686/cmov/libc-2.10.1.so
00fb2000-00fb4000 r--p 0013e000 08:01 1800/lib/tls/i686/cmov/libc-2.10.1.so
00fb4000-00fb5000 rw-p 00140000 08:01 1800/lib/tls/i686/cmov/libc-2.10.1.so
00fb5000-00fb8000 Rw-p 00000000 00:00 0
08048000-08049000 R-xp 00000000 08:01 303895/HOME/PANFENG/SEGFAULT/SEGFAULT3
08049000-0804a000 R--p 00000000 08:01 303895/HOME/PANFENG/SEGFAULT/SEGFAULT3
0804a000-0804b000 rw-p 00001000 08:01 303895/HOME/PANFENG/SEGFAULT/SEGFAULT3
09432000-09457000 Rw-p 00000000 00:00 0 [Heap]
b78cf000-b78d1000 Rw-p 00000000 00:00 0
b78df000-b78e1000 Rw-p 00000000 00:00 0
bfb67000-bfb7c000 Rw-p 00000000 00:00 0 [Stack]
5. Some Considerations
1, when there is a segment error, you should first think of the definition of the paragraph, from which to consider the cause of the error.
2. When using the pointer, remember to initialize the pointer after defining the pointer, and remember to judge whether it is null when used.
3, when using the array, notice whether the array is initialized, whether the array subscript is out of bounds, whether the array element exists, and so on.
4. When accessing variables, notice whether the variable occupies the address space has been released by the program.
5, in processing variables, pay attention to the variable format control is reasonable and so on.
6. Reference List
1, http://www.docin.com/p-105923877.html
2, http://blog.chinaunix.net/space.php?uid=317451&do=blog&id=92412
=======================================================================
The big circle Those things (original climbing peak @ Taobao)
Technical points: Architecture design, database, distributed computing and storage, Hadoop, C, Erlang, design patterns
Email:ypf412@163.com
Msn:ypf412@hotmail.com
Blog: http://www.cnblogs.com/panfeng412/
Micro Blog: http://weibo.com/moudayuan/