Linux section Error Details

Source: Internet
Author: User
Tags signal handler dmesg

by Falcon of


I wrote an early article: "Abominable" segmentation faults "of the preliminary summary of the network is reproduced very much. Over the years, the discussion of paragraph errors is still very enthusiastic, and the problem is still very common. So I'm going to comb the ins and outs of the problem in a systematic way here.

What is a segment error

Here is the definition from

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.

In addition, there is a basic comparison of the Chinese interpretation of the Internet:

The so-called segment error refers to the memory that is accessed exceeds the memory space given to the program by the system, usually this value is saved by GDTR, which is a 48-bit register, where the 32 bits are saved by the GDT that it points to, the last 13 bits are corresponding to the GDT's subscript, and the final 3 bits include whether the program is in memory In addition to the program's operating level in the CPU, the GDT points to a 64-bit table, in which the code snippet to run the program and the starting address of the data segment are stored, as well as information about the corresponding segment limit and page Exchange, the program run level, and the granularity of the memory, and so on. Once a program has crossed access, the CPU will have a corresponding exception protection, so segmentation fault appeared

By the above explanation, the segment error should be to access inaccessible memory, which either does not exist or is protected by the system.

Section error Log Analysis example

A typical example is the scanf use of a parameter error:

#include <stdio.h>int main(intchar *argv[]){        int i;         scanf("%d\n", i);        return0;}

Save the file as segfault-scanf.c . Which &i was written i .

Segment error message
$ make segfault-scanf$./segfault-scanf100segmentation fault (core dumped)
Segment Error Analysis
$ CATCHSEGV./segfault-scanf100segmentation fault (core dumped) * * * Segmentation faultregister Dump:rax: 0000000000000CA0 rbx:0000000000000040 rcx:0000000000000010 rdx:0000000000000000 rsi:0000000000000000 rdi:1999 999999999999 rbp:00007fffdbdf1010 r8:00007fbb45330060 r9:0000000000000000 r10:0000000000000ca0 r11:0000000000  000000 r12:0000000000000004 r13:0000000000000000 r14:00007fbb45330640 r15:000000000000000a rsp:00007fffdbdf0c20 rip:00007fbb44fc761a eflags:00010212 cs:0033 fs:0000 gs:0000 trap:0000000e error:00000006 oldmask:00000 cr2:00000000 fpucw:0000037f fpusw:00000000 tag:00000000 rip:00000000 rdp:00000000 ST (0) 0000 00000000000   00000 St (1) 0000 0000000000000000th (2) 0000 0000000000000000th (3) 0000 0000000000000000th (4) 0000 0000000000000000 St (5) 0000 0000000000000000 St (6) 0000 0000000000000000 St (7) 0000 0000000000000000 mxcsr:1f80 xmm0:000000000000000 00000000000000000 xmm1:00000000000000000000000000000000 xmm2:00000000000000000000000000000000 xmm3:00000000000000000000000000000000 XMM4: 00000000000000000000000000000000 xmm5:00000000000000000000000000000000 xmm6:00000000000000000000000000000000 XMM7 : 00000000000000000000000000000000 xmm8:00000000000000000000000000000000 xmm9:00000000000000000000000000000000 xmm10:00000000000000000000000000000000 xmm11:00000000000000000000000000000000 XMM12: 00000000000000000000000000000000 xmm13:00000000000000000000000000000000 xmm14:00000000000000000000000000000000 Xmm15:00000000000000000000000000000000backtrace:/lib/x86_64-linux-gnu/ (_IO_vfscanf+0x303a) [ 0x7fbb44fc761a]/lib/x86_64-linux-gnu/ (__isoc99_scanf+0x109) [0x7fbb44fce399]??:? (main) [0x400587]/lib/x86_64-linux-gnu/ (__libc_start_main+0xf5) [0x7fbb44f91ec5]??:? (_start) [0x400499] Memory map:00400000-00401000 R-xp 00000000 08:09 2903814 segfault-scanf00600000-00601000 r--p 00000000 08:09 2903814 SEGF ault-scanf00601000-00602000 rw-p 00001000 08: 2903814 segfault-scanf01b98000-01bbd000 Rw-p 00000000 00:00 0 [heap]7fbb44d5a000-7fbb44d70000 R-xp 00000000 08:02 171 0807/lib/x86_64-linux-gnu/ 00016000 08:02 1710807/lib/x86_64-linux-gnu/ rw-p 00015000 08:02 1710807/lib/x86_64-linux-gnu/libgcc_ R-xp 00000000 08:02 1731685/lib/x86_64-linux-gnu/ libc-2.19.so7fbb4512b000-7fbb4532b000---p 001bb000 08:02 1731685/lib/x86_64-linux-gnu/ libc-2.19.so7fbb4532b000-7fbb4532f000 r--p 001bb000 08:02 1731685/lib/x86_64-linux-gnu/ libc-2.19.so7fbb4532f000-7fbb45331000 rw-p 001bf000 08:02 1731685/lib/x86_64-linux-gnu/ libc-2.19.so7fbb45331000-7fbb45336000 Rw-p 00000000 00:00 07fbb45336000-7fbb4533a000 R-xp 00000000 08:02 1731696/lib/ x86_64-linux-gnu/libsegfault.so7fbb4533a000-7fbb45539000---p 00004000 08:02 1731696/lib/x86_64-linux-gnu/ libsegfault.so7fbb45539000-7fbb4553a000 r--p 00003000 08:02 1731696/lib/x86_64-linux-gnu/libsegfault.so7fbb4553a000-7fbb4553b000 rw-p 00004000 08:02 1731696/lib/x86_64-linux-gnu/ libsegfault.so7fbb4553b000-7fbb4555e000 R-xp 00000000 08:02 1731686/lib/x86_64-linux-gnu/ ld-2.19.so7fbb45729000-7fbb4572c000 Rw-p 00000000 00:00 07fbb4575a000-7fbb4575d000 Rw-p 00000000 00:00 07fbb4575d000-7fbb4575e000 r--p 00022000 08:02 1731686/lib/x86_64-linux-gnu/ld-2.19.so7fbb4575e000-7fbb4575f000 Rw-p 00023000 08:02 1731686/lib/x86_64-linux-gnu/ld-2.19.so7fbb4575f000-7fbb45760000 Rw-p 00000000 00:00 07fffdbdd2000-7fffdbdf3000 Rw-p 00000000 00:00 07fffdbdfe000-7fffdbe00000 R-xp 00000000 00:00 0 [VDSO] ffffffffff600000-ffffffffff601000 R-xp 00000000 00:00 0 [Vsyscall]

The above logs contain registers, callbacks, and memory image information. Where the callback part of the _IO_vfscanf problem is pointed out scanf . But I do not see clearly, you can use a gdb single-step tracking to confirm.

Information about the register we care about most:

trap:0000000e   error:00000006

arch/x86/include/asm/traps.h arch/x86/kernel/traps.c the types from and found SIGSEGV are:

/* interrupts/exceptions */enum {        ...        x86_trap_of,/            *  4, Overflow */        X86_TRAP_BR,/            *  5, Bound Range exceeded */        x86_trap_ts, /            * Ten, Invalid TSS *        / X86_TRAP_GP,/*, General            Protection Fault */        X86_TRAP_PF,/*,            Page Fault */        ...}

The Trap is 0xe, or 14, which is Page Fault.

The arch/x86/mm/fault.c error code is explained in detail:

/* Page fault error code bits: * *   bit 0 = =    0:no page found       1:protection fault *   bit 1 = =    0:read Access         1:write access *   bit 2 = =    0:kernel-mode Access  1:user-mode access *   bit 3 = =                           1:use of Reserved bit detected *   bit 4 = = 1:fault is an                           instruction fetch */enum x86_pf_error_code {        Pf_prot         =               
Examples of common segment errors

Here are some examples of common segment errors.

scanf parameter: Write &i as I
int i;scanf("%d", i);

Analysis : I is defined, the value is indeterminate, and scanf the value of I as a parameter into the scanf, and scanf will treat I as an address, the user input content into the place. The address is random and may not exist or be illegal at all.

sprintf/printf parameter:%d/%c written as%s
int i = 10;printf("%s", i);

Analysis : When printing a string, it is actually printing all the characters at the beginning of an address, where the integer is passed as an argument, the integer is treated as an address, and printf prints the character from this address until the value in a position is. If the integer represents an address that does not exist or is inaccessible, it is natural to access the memory--segmentation fault that should not be accessed.

Array access out of bounds
char test[1];printf("%c", test[1000000000]);

Note : It may also be reported as Bus Error, which may present a read or write to an unaligned address.

Write read-only memory
char *ptr = "test";strcpy(ptr, "TEST");

analysis : PTR is defined as "test", is a read-only memory segment, cannot be written directly, and is written to be allocated with malloc from the heap or defined as an array of strings.

Stack Overflow
void main(){    main();}

Analysis : The above is actually a recursive invocation of a dead loop, which can cause a stack overflow.

Pthread_create () after failure Pthread_join ()
#define THREAD_MAX_NUMpthread_t thread[THREAD_MAX_NUM];

Analysis : Create individual threads with Pthread_create (), and then use Pthread_join () to wait for the thread to end. Just started to wait directly, when the creation of the thread is successful, pthread_join () can wait until the end of each thread, but once the creation of the thread fails, with Pthread_join () to wait for the non-existent thread, there will naturally be unknown memory, resulting in the occurrence of a segment error. The workaround is to initialize the thread array before creating the thread, and at the end of the wait thread, determine if the thread is the initial value, and if so, the thread is not created successfully, so it cannot wait for the pull.


In all cases,

    • Remember to initialize when the pointer is defined, and remember to determine if it is NULL when used
    • Remember to initialize when using an array, to check if the array subscript is out of bounds, whether the array element exists, etc.
    • Whether the variable's format control is reasonable when the variable is processed

Others need to accumulate based on experience, and more examples will continue to be appended to the list above.

In addition, it is important to master some basic analysis and debugging tools, even if you encounter new problems such as to know how to deal with.

Analysis and commissioning Tools

In addition to the simplest methods, catchsegv there are many ways to use the analysis method, and their application scenarios vary.


The tool is used to catch a segment error, and it loads a pre-written library (/lib/ through the dynamic loader ( preload mechanism (preload) to capture error messages for broken errors.

gdb ./segfault-scanf ...Reading symbols from ./segfault-scanf...done.(gdb) rStarting program: segfault-scanf 100Program received signal SIGSEGV, Segmentation fault.0x00007ffff7a6b61a in _IO_vfscanf_internal (s=<optimized out>,     format=<optimized out>, [email protected]=0x7fffffffddc8,     [email protected]=0x0) at vfscanf.c:18571857    vfscanf.c: No such file or directory.(gdb) bt#0  0x00007ffff7a6b61a in _IO_vfscanf_internal (s=<optimized out>,     format=<optimized out>, [email protected]=0x7fffffffddc8,     [email protected]=0x0) at vfscanf.c:1857#1  0x00007ffff7a72399 in __isoc99_scanf (format=<optimized out>)    at isoc99_scanf.c:37#2  0x0000000000400580 in main ()
$ ulimit -c 1024$ gdb segfault-scanf ./core Reading symbols from segfault-scanf...done.[New LWP 16913]Core was generated by `./segfault-scanf‘.Program terminated with signal SIGSEGV, Segmentation fault.#0  0x00007fd2d24ec61a in _IO_vfscanf_internal (s=<optimized out>,     format=<optimized out>, [email protected]=0x7fff14dfa668,     [email protected]=0x0) at vfscanf.c:18571857    vfscanf.c: No such file or directory.
In-Program capture SIGSEGVSignal and start gdb
#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <string.h>voidDumpintSigno) {Charbuf[1024x768];Charcmd[1024x768]; FILE *FH;snprintf(BUF,sizeof(BUF),"/proc/%d/cmdline", 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] =' + ';snprintf(CMD,sizeof(CMD),"GdB%s%d", buf, Getpid ()); System (CMD);Exit(0);}intMainintargcChar*argv[]) {intI Signal (SIGSEGV, &dump);scanf("%d\n", i);return 0;}

Use the following:

$ gcc -g -rdynamic -o segfault-scanf segfault-scanf.c$ sudo ./segfault-scanf100(gdb) bt#0  0x00007fb743e065cc in __libc_waitpid (pid=16988,     [email protected]=0x7fffb51d8fe0, [email protected]=0)    at ../sysdeps/unix/sysv/linux/waitpid.c:31#1  0x00007fb743d8b1d2 in do_system (line=<optimized out>)    at ../sysdeps/posix/system.c:148#2  0x0000000000400ba1 in dump (signo=11) at segfault-scanf.c:21#3  <signal handler called>#4  0x00007fb743d9c61a in _IO_vfscanf_internal (s=<optimized out>,     format=<optimized out>, [email protected]=0x7fffb51da318,     [email protected]=0x0) at vfscanf.c:1857#5  0x00007fb743da3399 in __isoc99_scanf (format=<optimized out>)    at isoc99_scanf.c:37#6  0x0000000000400bdd in main (argc=1, argv=0x7fffb51da508)    at segfault-scanf.c:31
In-Program capture SIGSEGVSignal and call backtrace()Get callback
#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <string.h>voidDumpintSigno) {void*Array[Ten]; size_t size;Char**strings;        size_t i; Size = BackTrace (Array,Ten); 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);}intMainintargcChar*argv[]) {intI Signal (SIGSEGV, &dump);scanf("%d\n", i);return 0;}

Use the following:

$ ./segfault-scanf100Obtained 7 stack frames../segfault-scanf() [0x40077e]/lib/x86_64-linux-gnu/ [0x7f249fa43c30]/lib/x86_64-linux-gnu/ [0x7f249fa6461a]/lib/x86_64-linux-gnu/ [0x7f249fa6b399]./segfault-scanf-call-backtrace() [0x400837]/lib/x86_64-linux-gnu/ [0x7f249fa2eec5]./segfault-scanf-call-backtrace() [0x400699]

In addition, you can dmesg view the kernel information and pass objdump or addr2line turn IP addresses into lines of code, but the usage is not catchsegv easy. dmesgGets the kernel information printed by the arch/x86/mm/fault.c: show_signal_msg() .


Paragraph error is a common bug in C language development under Linux, this article from the principle, case, analysis and debugging methods, and other aspects of the detailed analysis, hoping to help.

If you want to know more, we recommend reading the following resources.

    • Segmentation Fault in linux--reasons and avoidance
    • A summary of the causes and debugging methods of the next segment error in Linux environment
    • Debugging of Segment Error bugs
    • Segmentation fault
    • Segmentation fault where the hell is doer
    • TRAP.C file analysis of the Linux kernel
    • Linux kernel interrupts, exceptions
    • Linux under X86 architecture IDT Parsing
    • Segmentation Fault Error Decoder
    • Understanding a Kernel oops!

Linux section Error Details

Related Article

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: 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.