A summary of the causes and debugging methods of the next segment error in Linux environment

Source: Internet
Author: User
Tags gdb debugger dmesg

Recently in the Linux environment to do C language project, because it is on the basis of an original project two development, and project engineering is huge and complex, there are many problems, the most encountered, the longest time of the problem is the famous "segment Error" (Segmentation Fault). Take this opportunity system to learn a bit, here to the Linux Environment section error to do a summary, to facilitate the subsequent troubleshooting and resolution of similar problems.

1. What is the segment error?

In a word, a segment error means that the memory accessed exceeds the memory space set by the system to the program, such as accessing a nonexistent memory address, accessing a system-protected memory address, accessing a read-only memory address, and so on. A precise definition of "segment error" is posted here (refer to 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 if a program attempts to access a memory location that it's not allowed to access , or attempts to access a memory-location in a-a-is-not-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 these events as Address or Bus errors.

Segmentation is one approach to memory management and protection in the operating system. It had been superseded by paging for most purposes, but much of the terminology of segmentation was still used, "Segmentati On fault "being an example. Some operating systems still has 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 of that accesses invalid memory receives the status_access_violation exception.
2. Segment error causes 2.1 access to a memory address that does not exist
#include <stdio.h>
#include <stdlib.h>
void Main ()
{
int *ptr = NULL;
*ptr = 0;
}
2.2 Accessing system-protected memory addresses
#include <stdio.h>
#include <stdlib.h>
void Main ()
{
int *ptr = (int *) 0;
*ptr = 100;
}
2.3 Access to read-only memory addresses
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void Main ()
{
Char *ptr = "Test";
strcpy (PTR, "TEST");
}
2.4 Stack Overflow
#include <stdio.h>
#include <stdlib.h>
void Main ()
{
Main ();
}

Wait for other reasons.

3. Getting the segment error message

When the program has a segment error, the message is very small, there are several ways to view the occurrence of a segment error.

3.1 DMESG

DMESG can display information that is stored in the kernel when the application crash out. As shown below, the DMESG command allows you to see the name of the program where the 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 as an example:

[Email protected]:~/segfault$ DMESG
[2329.479037] segfault3[2700]: Segfault at 80484e0 IPs 00d2906a SP bfbbec3c error 7 in libc-2.10.1.so[cb4000+13e000]
3.2-g

When using the source code of the GCC compiler, add the-G parameter, which allows the generated binaries to include useful information that can be used for GDB debugging. Take program 2.3 as an example:

[Email protected]:~/segfault$ gcc-g-o segfault3 segfault3.c
3.3 nm

Use the NM command to list symbol tables in binaries, including symbolic addresses, symbol types, symbol names, and so on, to help locate where a segment error occurred. Take program 2.3 as an example:

[Email protected]:~/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 [email protected] @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 [email protected] @GLIBC_2.0
3.4 LDD

Use the LDD command to view the shared link library dependencies of a binary program, including the name of the library, the start address, to determine whether the segment error occurred in your own program or in a shared library that depends on it. Take program 2.3 as an example:

[Email protected]:~/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 for segment error 4.1 using printf output information

This is the simplest but often very effective debugging method, perhaps it is the programmer with the most debugging mode. Simply put, the output information like printf is added near the program's important code, so you can track and print out where a segment error might appear in your code.

To facilitate this approach, you can use the conditional compilation Directives #ifdef Debug and #endif to wrap the printf functions together. This allows the debugging information to be viewed when the program is compiled with the-ddebug parameter, otherwise the debug information will not be displayed without the parameter.

4.2 Debugging steps with GCC and gdb4.2.1

1, in order to be able to use the GDB debugger, in the compile phase with the-G parameter, program 2.3 as an example:

[Email protected]:~/segfault$ gcc-g-o segfault3 segfault3.c

2. Use the GDB command to debug the program:


GNU gdb (GDB) 7.0-ubuntu
Copyright (C) Software Foundation, Inc.
License gplv3+: GNU GPL version 3 or later This was free software:you was free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "Show copying"
and "Show warranty" for details.
This GDB is configured as "I486-linux-gnu".
For bugs reporting instructions, please see:
Reading symbols From/home/panfeng/segfault/segfault3...done.

3. After entering GDB, run the program:

(GDB) Run


Program received signal SIGSEGV, segmentation fault.
0x001a306a in memcpy () from/lib/tls/i686/cmov/libc.so.6

From the output, the program 2.3 received SIGSEGV signal, triggering a segment error, and prompted the address 0x001a306a, call memcpy the wrong, located in the/lib/tls/i686/cmov/libc.so.6 library.

4. After debugging, enter the QUIT command to exit GDB:

(GDB) quit
A debugging session is active.

Inferior 1 [process 3207] would be killed.

Quit anyway? (Y or N) y
4.2.2 Applicable Scenarios

1. Use only when it is possible to determine that the program is bound to have a segment error.

2, when the source code of the program can be obtained, use the-G parameter to compile the program.

3, generally used for testing stage, the production environment gdb will have side effects: To make the program run slow, not stable, and so on.

4, even in the testing phase, if the program is too complex, GDB can not handle.

4.3 Using the core file and GDB

In section 4.2 mentioned in the paragraph error will trigger the SIGSEGV signal, through the man 7 signal, you can see the SIGSEGV default handler will print the error message, and produce a core file, so we can rely on the program exception exits when the core files generated in the debug information , use the GDB tool to debug a segment error in your program.

4.3.1 Debugging steps

1, in some Linux versions, the default is not to produce a core file, you can first look at the system core file size limit:

[Email protected]:~/segfault$ ulimit-c
0

2, you can see the default settings, the local Linux environment in the event of a segment error will not automatically generate a core file, the following set the size limit of the core file (in kilobytes):

[Email protected]:~/segfault$ ulimit-c 1024
[Email protected]:~/segfault$ ulimit-c
1024

3, run the program 2.3, the occurrence of a segment error generated core file:

[Email protected]:~/segfault$./SEGFAULT3
Segment error (Core dumped)

4. Load the core file and debug with the GDB tool:

[Email protected]:~/segfault$ gdb/SEGFAULT3./core
GNU gdb (GDB) 7.0-ubuntu
Copyright (C) Software Foundation, Inc.
License gplv3+: GNU GPL version 3 or later This was free software:you was free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "Show copying"
and "Show warranty" for details.
This GDB is configured as "I486-linux-gnu".
For bugs reporting instructions, please see:
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 one, segmentation fault.
#0 0x0018506a in memcpy () from/lib/tls/i686/cmov/libc.6

As seen 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 Scenarios

1, suitable for debugging the program in the actual build environment of the segment error (that is, without re-occurrence of a segment error in the case of the recurrence of a segment error).

2, when the program is very complex, the core file is quite large, the method is not available.

4.4 Debugging steps with objdump4.4.1

1. Use the DMESG command to find the most recent segment error output information:

[Email protected]:~/segfault$ DMESG
... ...
[17257.502808] segfault3[3320]: segfault at 80484e0 IP 0018506a SP bfc1cd6c error 7 in libc-2.10.1.so[110000+13e000]

What 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 file:

[Email protected]:~/segfault$ objdump-d/SEGFAULT3 > Segfault3dump

Where the generated Segfault3dump file contains the assembly code for the SEGFAULT3 of the binaries.

3. In the Segfault3dump file, look for the address where the segment error occurred:

[Email protected]:~/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%eax,0x4 mov (%ESP)
137-8048406:8B 1c MOV 0x1c (%ESP),%eax
138-804840A:89 mov%eax, (%ESP)
139-804840d:e8 0a FF FF call 804831c <[email protected]>
140-8048412:c9 leave
141-8048413:C3 ret

Through the above assembly code analysis, learned that the section error occurred in the main function, the corresponding assembly instruction is MOVL $0x80484e0,0x1c (%ESP), the next open the program's source code, find assembly instructions corresponding to the source code, also positioned to the paragraph error.

4.4.2 Applicable Scenarios

1, does not need the-G parameter compilation, does not need to rely on the core file, but needs to have certain assembly language Foundation.

2, if the GCC compiler optimization parameters (-O1,-O2,-O3) are used, the generated assembly instructions will be optimized, making the debugging process somewhat difficult.

4.5 Using CATCHSEGV

The CATCHSEGV command is specifically designed to catch a segment error, and it loads a pre-written library (/lib/libsegfault.so) through the dynamic loader (ld-linux.so) preload mechanism (preload) to capture error messages for broken errors.

[Email protected]:~/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 paragraph error, you should first think of the definition of the paragraph error, from which to consider the cause of the cause of the error.

2, when using the pointer, the pointer is defined, remember to initialize the pointer, when used to remember to determine whether NULL.

3. When using an 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 a variable, notice whether the address space occupied by the variable has been released by the program.

5, when processing variables, pay attention to the variable format control is reasonable and so on.

6. List of resources

1, http://www.docin.com/p-105923877.html

2, http://blog.chinaunix.net/space.php?uid=317451&do=blog&id=92412

A summary of the causes and debugging methods of the next segment error in Linux environment

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.