導航:首頁 > 源碼編譯 > 編譯文件時segfault

編譯文件時segfault

發布時間:2022-12-14 17:00:48

Ⅰ 在ubuntu編譯android文件時遇到下面的問題

很明顯就是這個:arm-linux-androideabi-g++找不到,進入你的這個目錄下:prebuilt/linux-x86/ccache/ccache prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/

然後看下是否有以下文件或鏈接文件:

arm-linux-androideabi-addr2line arm-linux-androideabi-gprof
arm-linux-androideabi-ar arm-linux-androideabi-ld
arm-linux-androideabi-as arm-linux-androideabi-ld.bfd
arm-linux-androideabi-c++ arm-linux-androideabi-ld.gold
arm-linux-androideabi-c++filt arm-linux-androideabi-nm
arm-linux-androideabi-cpp arm-linux-androideabi-obj
arm-linux-androideabi-g++ arm-linux-androideabi-objmp
arm-linux-androideabi-gcc arm-linux-androideabi-ranlib
arm-linux-androideabi-gcc-4.4.3 arm-linux-androideabi-readelf
arm-linux-androideabi-gccbug arm-linux-androideabi-run
arm-linux-androideabi-gcov arm-linux-androideabi-size
arm-linux-androideabi-gdb arm-linux-androideabi-strings
arm-linux-androideabi-gdbtui arm-linux-androideabi-strip

特別是看下這個:arm-linux-androideabi-g++

若是沒有從別的地方(如你同事朋友那邊拷一份過)一份放在這里。若是軟鏈接文件,看看鏈接指向的文件是不是不存在了,不存在也一樣一份好的放在鏈接指向的文件的地方。

Ⅱ 關於C語言在編譯時常出現的錯誤有哪些

1、fatal error C1010: unexpected end of file while looking for precompiled header directive。

尋找預編譯頭文件路徑時遇到了不該遇到的文件尾。(一般是沒有#include "stdafx.h")

2、fatal error C1083: Cannot open include file: 'R…….h': No such file or directory

不能打開包含文件「R…….h」:沒有這樣的文件或目錄。

3、error C2011: 'C……': 'class' type redefinition

類「C……」重定義。

4、error C2018: unknown character '0xa3'

不認識的字元'0xa3'。(一般是漢字或中文標點符號)

5、error C2057: expected constant expression

希望是常量表達式。(一般出現在switch語句的case分支中)

6、error C2065: 'IDD_MYDIALOG' : undeclared identifier

「IDD_MYDIALOG」:未聲明過的標識符。

7、error C2082: redefinition of formal parameter 'bReset'

函數參數「bReset」在函數體中重定義。

8、error C2143: syntax error: missing ':' before '{'

句法錯誤:「{」前缺少「;」。

9、error C2146: syntax error : missing ';' before identifier 'dc'

句法錯誤:在「dc」前丟了「;」。

10、error C2196: case value '69' already used

值69已經用過。(一般出現在switch語句的case分支中)

11、error C2509: 'OnTimer' : member function not declared in 'CHelloView'

成員函數「OnTimer」沒有在「CHelloView」中聲明。

12、error C2511: 'reset': overloaded member function 'void (int)' not found in 'B'

重載的函數「void reset(int)」在類「B」中找不到。

13、error C2555: 'B::f1': overriding virtual function differs from 'A::f1' only by return type or calling convention

類B對類A中同名函數f1的重載僅根據返回值或調用約定上的區別。

14、error C2660: 'SetTimer' : function does not take 2 parameters

「SetTimer」函數不傳遞2個參數。

15、warning C4035: 'f……': no return value

「f……」的return語句沒有返回值。

16、warning C4553: '= =' : operator has no effect; did you intend '='?

沒有效果的運算符「= =」;是否改為「=」?

17、warning C4700: local variable 'bReset' used without having been initialized

局部變數「bReset」沒有初始化就使用。

18、error C4716: 'CMyApp::InitInstance' : must return a value

「CMyApp::InitInstance」函數必須返回一個值。

19、LINK : fatal error LNK1168: cannot open Debug/P1.exe for writing

連接錯誤:不能打開P1.exe文件,以改寫內容。(一般是P1.Exe還在運行,未關閉)

20、error LNK2001: unresolved external symbol "public: virtual _ _thiscall C……::~C……(void)"

連接時發現沒有實現的外部符號(變數、函數等)。

function call missing argument list 調用函數的時候沒有給參數。

member function definition looks like a ctor, but name does not match enclosing class 成員函數聲明了但沒有使用

unexpected end of file while looking for precompiled header directive 在尋找預編譯頭文件時文件意外結束,編譯不正常終止可能造成這種情況

Ⅲ 編譯時出現頭文件找不到的情況該如何解決 …

你是否有試過編譯一個文件時,老是因為缺掉一些頭或庫文件而編譯不通過呢?下面給出一種方法來解決這個問題:
1.先安裝apt-filesudoapt-get install apt-filesudoapt-file update
2.假如make時,出現
main.c:21:21:
error: gtk/gtk.h: No such file or directory使用:sudoapt-file searchgtk.h
運行以上命令可能返回好多包,精簡一下sudoapt-file search gtk/gtk.h結果如下:
# apt-file search gtk/gtk.h
libgfcui-dev:
usr/include/gfc-2.0/gfc/gtk/gtk.hh
libgtk+2.0-directfb-dev:
usr/include/directfb/gtk-2.0/gtk/gtk.h
3.最後定位該頭文件所在的位置
wyylling@ubuntu:~/Gnome$ locate gtk.h
將該/usr/include/gtk-2.0/加入頭文件搜索路徑中即可

Ⅳ linux 出現 segment fault怎麼解決

1. 段錯誤是什麼
一句話來說,段錯誤是指訪問的內存超出了系統給這個程序所設定的內存空間,例如訪問了不存在的內存地址、訪問了系統保護的內存地址、訪問了只讀的內存地址等等情況。這里貼一個對於「段錯誤」的准確定義(參考Answers.com):

A segmentation fault (often shortened to segfault) is a particular error condition that can occur ring the operation of computer software. In short, a segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (e.g., attempts to write to a read-only location, or 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 has been superseded by paging for most purposes, but much of the terminology of segmentation is still used, "segmentation 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. 段錯誤產生的原因
2.1 訪問不存在的內存地址

#include<stdio.h>
#include<stdlib.h>
void main()
{
int *ptr = NULL;
*ptr = 0;
}

2.2 訪問系統保護的內存地址

#include<stdio.h>
#include<stdlib.h>
void main()
{
int *ptr = (int *)0;
*ptr = 100;
}

2.3 訪問只讀的內存地址

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main()
{
char *ptr = "test";
strcpy(ptr, "TEST");
}

2.4 棧溢出

#include<stdio.h>
#include<stdlib.h>
void main()
{
main();
}

等等其他原因。
3. 段錯誤信息的獲取
程序發生段錯誤時,提示信息很少,下面有幾種查看段錯誤的發生信息的途徑。
3.1 dmesg
dmesg可以在應用程序crash掉時,顯示內核中保存的相關信息。如下所示,通過dmesg命令可以查看發生段錯誤的程序名稱、引起段錯誤發生的內存地址、指令指針地址、堆棧指針地址、錯誤代碼、錯誤原因等。以程序2.3為例:
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
使用gcc編譯程序的源碼時,加上-g參數,這樣可以使得生成的二進制文件中加入可以用於gdb調試的有用信息。以程序2.3為例:
panfeng@ubuntu:~/segfault$ gcc -g -o segfault3 segfault3.c

3.3 nm
使用nm命令列出二進制文件中的符號表,包括符號地址、符號類型、符號名等,這樣可以幫助定位在哪裡發生了段錯誤。以程序2.3為例:

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_mmy
080483e4 T main
U memcpy@@GLIBC_2.0

3.4 ldd
使用ldd命令查看二進製程序的共享鏈接庫依賴,包括庫的名稱、起始地址,這樣可以確定段錯誤到底是發生在了自己的程序中還是依賴的共享庫中。以程序2.3為例:
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. 段錯誤的調試方法
4.1 使用printf輸出信息
這個是看似最簡單但往往很多情況下十分有效的調試方式,也許可以說是程序員用的最多的調試方式。簡單來說,就是在程序的重要代碼附近加上像printf這類輸出信息,這樣可以跟蹤並列印出段錯誤在代碼中可能出現的位置。
為了方便使用這種方法,可以使用條件編譯指令#ifdef DEBUG和#endif把printf函數包起來。這樣在程序編譯時,如果加上-DDEBUG參數就能查看調試信息;否則不加該參數就不會顯示調試信息。
4.2 使用gcc和gdb
4.2.1 調試步驟
1、為了能夠使用gdb調試程序,在編譯階段加上-g參數,以程序2.3為例:
panfeng@ubuntu:~/segfault$ gcc -g -o segfault3 segfault3.c

2、使用gdb命令調試程序:

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 <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show ing"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/panfeng/segfault/segfault3...done.
(gdb)

3、進入gdb後,運行程序:

(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)

從輸出看出,程序2.3收到SIGSEGV信號,觸發段錯誤,並提示地址0x001a306a、調用memcpy報的錯,位於/lib/tls/i686/cmov/libc.so.6庫中。
4、完成調試後,輸入quit命令退出gdb:

(gdb) quit
A debugging session is active.

Inferior 1 [process 3207] will be killed.

Quit anyway? (y or n) y

4.2.2 適用場景
1、僅當能確定程序一定會發生段錯誤的情況下使用。
2、當程序的源碼可以獲得的情況下,使用-g參數編譯程序。
3、一般用於測試階段,生產環境下gdb會有副作用:使程序運行減慢,運行不夠穩定,等等。
4、即使在測試階段,如果程序過於復雜,gdb也不能處理。
4.3 使用core文件和gdb
在4.2節中提到段錯誤會觸發SIGSEGV信號,通過man 7 signal,可以看到SIGSEGV默認的handler會列印段錯誤出錯信息,並產生core文件,由此我們可以藉助於程序異常退出時生成的core文件中的調試信息,使用gdb工具來調試程序中的段錯誤。
4.3.1 調試步驟
1、在一些Linux版本下,默認是不產生core文件的,首先可以查看一下系統core文件的大小限制:
panfeng@ubuntu:~/segfault$ ulimit -c
0

2、可以看到默認設置情況下,本機Linux環境下發生段錯誤時不會自動生成core文件,下面設置下core文件的大小限制(單位為KB):
panfeng@ubuntu:~/segfault$ ulimit -c 1024
panfeng@ubuntu:~/segfault$ ulimit -c
1024

3、運行程序2.3,發生段錯誤生成core文件:
panfeng@ubuntu:~/segfault$ ./segfault3
段錯誤 (core mped)

4、載入core文件,使用gdb工具進行調試:

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 <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show ing"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/panfeng/segfault/segfault3...done.

warning: Can't read pathname for load map: 輸入/輸出錯誤.
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 was generated by `./segfault3'.
Program terminated with signal 11, Segmentation fault.
#0 0x0018506a in memcpy () from /lib/tls/i686/cmov/libc.6

從輸出看出,同4.2.1中一樣的段錯誤信息。
5、完成調試後,輸入quit命令退出gdb:
(gdb) quit

4.3.2 適用場景
1、適合於在實際生成環境下調試程序的段錯誤(即在不用重新發生段錯誤的情況下重現段錯誤)。
2、當程序很復雜,core文件相當大時,該方法不可用。
4.4 使用objmp
4.4.1 調試步驟
1、使用dmesg命令,找到最近發生的段錯誤輸出信息:
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]

其中,對我們接下來的調試過程有用的是發生段錯誤的地址:80484e0和指令指針地址:0018506a。
2、使用objmp生成二進制的相關信息,重定向到文件中:
panfeng@ubuntu:~/segfault$ objmp -d ./segfault3 > segfault3Dump

其中,生成的segfault3Dump文件中包含了二進制文件的segfault3的匯編代碼。
3、在segfault3Dump文件中查找發生段錯誤的地址:

panfeng@ubuntu:~/segfault$ grep -n -A 10 -B 10 "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 20 sub $0x20,%esp
131: 80483ed: c7 44 24 1c e0 84 04 movl $0x80484e0,0x1c(%esp)
132- 80483f4: 08
133- 80483f5: b8 e5 84 04 08 mov $0x80484e5,%eax
134- 80483fa: c7 44 24 08 05 00 00 movl $0x5,0x8(%esp)
135- 8048401: 00
136- 8048402: 89 44 24 04 mov %eax,0x4(%esp)
137- 8048406: 8b 44 24 1c mov 0x1c(%esp),%eax
138- 804840a: 89 04 24 mov %eax,(%esp)
139- 804840d: e8 0a ff ff ff call 804831c <memcpy@plt>
140- 8048412: c9 leave
141- 8048413: c3 ret

通過對以上匯編代碼分析,得知段錯誤發生main函數,對應的匯編指令是movl $0x80484e0,0x1c(%esp),接下來打開程序的源碼,找到匯編指令對應的源碼,也就定位到段錯誤了。
4.4.2 適用場景
1、不需要-g參數編譯,不需要藉助於core文件,但需要有一定的匯編語言基礎。
2、如果使用了gcc編譯優化參數(-O1,-O2,-O3)的話,生成的匯編指令將會被優化,使得調試過程有些難度。
4.5 使用catchsegv
catchsegv命令專門用來撲獲段錯誤,它通過動態載入器(ld-linux.so)的預載入機制(PRELOAD)把一個事先寫好的庫(/lib/libSegFault.so)載入上,用於捕捉斷錯誤的出錯信息。

panfeng@ubuntu:~/segfault$ catchsegv ./segfault3
Segmentation fault (core mped)
*** Segmentation fault
Register mp:

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:

java程序編譯通過但是運行時顯示「找不到或無法載入主類 helloworld 」 ,怎麼解決

既然javac編譯已經通過,這說明變數java-home已經配置的沒有問題了。

(java-home對應的變數值為javac.exe所在的路徑;一般是在安裝路徑下,例如c:Program FilesJavajdk1.7.0_45in)。

那第一種可能就是:問題就出在Path變數對應的變數值上或者是新建用戶變數classpath上有問題,你重新配置一下。Path對應的變數值是在原來的變數值前面加上%Java_Home%。

第二種可能就是:你的環境變數都是正確的,只是你編譯的java源文件中,主函數public static void main(String args[]){}沒有寫在main這個類中。

一個java源文件可以寫很多類,編譯的時候javac源文件之後,每個類生成一個class文件。你去運行的時候,並不一定是去java源文件名,而是去java主函數所在的那個類名。

第三種可能就是:像intopass說的那樣,你在eclipse寫的時候裡面會有package,你把它刪掉試試。

Ⅵ 在飛思卡爾ARM9開發板上交叉編譯運行了一個helloworld都報segmentation fault

段錯誤一般是指針訪問越界造成的,如:intbuf[10];for(inti=0;;i++){if(*buf[i]==100)printf()..}和交叉編譯沒有關系,你檢查一下你的代碼吧。

Ⅶ 編譯一個CPP文件時,出現這個錯誤怎麼辦

因為在工程編譯的時候各個.cpp文件依次單獨編譯,最後才連接到一起,當在編譯main.cpp文件時,看到main.cpp文件中有#include「2.cpp」文件時就把2.cpp中的內容和main.cpp一起編譯生成main.obj文件。別忘了2.cpp文件也是.cpp文件也要單獨編譯,編譯完2.cpp文件生成2.obj文件後。再將所有編譯後的.obj文件連接到一生成.exe文件。這時就會發現2.obj中的內容main.obj中也有(因為main.cpp中#include「2.cpp」)。所以會出現重復定義的錯誤。
這時你可能又會想到把2.cpp文件改名為2.h在main.cpp文件中#include「2.h」不就行了。因為.h文件不會單獨編譯。確實是這樣。將2.cpp改為2.h後不管工程目錄中有沒有添加2.h文件都可以。可是前面說了.h文件中最好只放聲明。(不失為一個解決問題的辦法)
extern可以置於變數或者函數前,以表示變數或者函數的定義在別的文件中,提示變壓器遇到此變數和函數時在其他模塊中尋找其定義。另外,extern也可用來進行鏈接指定。
關於extern更詳細的解釋請看網路
所以我們只需這樣:如果在1.cpp中要調用2.cpp中的函數,不要在1.cpp中#include「2.cpp」,只需在1.cpp中聲明一下要調用的函數,並且聲明前加關鍵字extern

Ⅷ 如何分析 coremp vs2012

coremp是我們在調試程序時經常碰到的問題,分析coremp的方法多種多樣:分析日誌;
編譯一個含符號表的debug版binary,在產生coremp後,使用一些調試工具gdb,dbx等分析core文件。這里介紹一種不藉助於日誌和gdb等工具,完全手工分析的辦法。
以常見的非法地址訪問引起的coremp為例,它會觸發11號信號----SIGSEGV.

#define STACK_BACK_SIZE 0x100
void SegFaultHandler(int signo)
{
int trace;
int *p = &trace;
int i;
for(i = 0; i < STACK_BACK_SIZE; i++)
syslog(LOG_DEBUG, "stack: %p:%x", p,*p++);
exit(signo);
}

void main()
{
signal(SIGSEGV, SegFaultHandler);
... ...
}

在產生coremp時,觸發信號SIGSEGV,由於其處理函數已被注冊為SegvHandler,則SegvHandler被調用。
SegvHandler所做的就是列印出當前棧上STACK_BACK_SIZE個整數。根據這STACK_BACK_SIZE個整數,再反匯編binary代碼,就可以確定coremp所產生的指令。
這是因為如果某條指令產生coremp,那麼SegvHandler的返回地址就是該指令的下一條指令,當然實際在coremp發生時,系統可能會增加對libc.so中mutex_lock等的調用,再調用SegvHandle,棧空間是:
--------->SegFaultHandler (棧頂)
---------------->mutex_lock(libc.so)
-------------------------->引起coremp指令的下一條指令
如果最終編譯生成的binary文件是a.out,使用readelf或objmp將a.out反匯編,就可以知道棧空間上的對應內容,也就是SegFaultHandler中列印出的各值的含義,不外乎是返回地址,保存的寄存器值和局部變數等。

如果是在linux平台下,那麼就不需要分析符號表,而可以調用backtrace來打出當前調用棧從而知道哪個函數導致coremp,但注意link時要加上 -rdynamic選項,否則符號表內容不清楚:
#include <execinfo.h>

void print_trace()
{
void *array[40];
size_t size;
char **strings;
size_t i;

size = backtrace (array, 40);
strings = backtrace_symbols (array, size);

for (i = 0; i < size; i++)
{
printf("##callstack##%s\n", strings[i]);

}
printf("\n");
free (strings);

}

void SegFaultHandler(int signo)
{
int trace;
print_trace();
exit(signo);
}

void main()
{
signal(SIGSEGV, SegFaultHandler);
... ...
}

Ⅸ 編譯php,make test的時候出錯,大家幫看看是什麼原因。

Can't bind to LDAP Server - [-1]
ldap_open() 函數打開一個到LDAP伺服器的聯接。
如果出錯,返回-1,並在LDAP結構中設置ld_errno域。
建議重下個安裝文件試試

Ⅹ linux c 段錯誤如何定位

1. 段錯誤是什麼
一句話來說,段錯誤是指訪問的內存超出了系統給這個程序所設定的內存空間,例如訪問了不存在的內存地址、訪問了系統保護的內存地址、訪問了只讀的內存地址等等情況。這里貼一個對於「段錯誤」的准確定義(參考Answers.com):
A segmentation fault (often shortened to segfault) is a particular error condition that can occur ring the operation of computer software. In short, a segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (e.g., attempts to write to a read-only location, or 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 has been superseded by paging for most purposes, but much of the terminology of segmentation is still used, "segmentation 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. 段錯誤產生的原因
2.1 訪問不存在的內存地址
#include<stdio.h>
#include<stdlib.h>
void main()
{
int *ptr = NULL;
*ptr = 0;
}
2.2 訪問系統保護的內存地址
#include<stdio.h>
#include<stdlib.h>
void main()
{
int *ptr = (int *)0;
*ptr = 100;
}
2.3 訪問只讀的內存地址
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main()
{
char *ptr = "test";
strcpy(ptr, "TEST");
}
2.4 棧溢出
#include<stdio.h>
#include<stdlib.h>
void main()
{
main();
}
等等其他原因。
3. 段錯誤信息的獲取
程序發生段錯誤時,提示信息很少,下面有幾種查看段錯誤的發生信息的途徑。
3.1 dmesg
dmesg可以在應用程序crash掉時,顯示內核中保存的相關信息。如下所示,通過dmesg命令可以查看發生段錯誤的程序名稱、引起段錯誤發生的內存地址、指令指針地址、堆棧指針地址、錯誤代碼、錯誤原因等。以程序2.3為例:
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
使用gcc編譯程序的源碼時,加上-g參數,這樣可以使得生成的二進制文件中加入可以用於gdb調試的有用信息。以程序2.3為例:
panfeng@ubuntu:~/segfault$ gcc -g -o segfault3 segfault3.c
3.3 nm
使用nm命令列出二進制文件中的符號表,包括符號地址、符號類型、符號名等,這樣可以幫助定位在哪裡發生了段錯誤。以程序2.3為例:
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_mmy
080483e4 T main
U memcpy@@GLIBC_2.0
3.4 ldd
使用ldd命令查看二進製程序的共享鏈接庫依賴,包括庫的名稱、起始地址,這樣可以確定段錯誤到底是發生在了自己的程序中還是依賴的共享庫中。以程序2.3為例:
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)

閱讀全文

與編譯文件時segfault相關的資料

熱點內容
圖像壓縮編碼實現 瀏覽:66
特色功能高拋低吸線副圖指標源碼 瀏覽:69
西方哲學史pdf羅素 瀏覽:872
python最常用模塊 瀏覽:182
溫州直播系統源碼 瀏覽:110
程序員在上海買房 瀏覽:382
生活解壓游戲機 瀏覽:907
季羨林pdf 瀏覽:716
php支付寶介面下載 瀏覽:814
ipad怎麼把app資源庫關了 瀏覽:301
量柱比前一天多源碼 瀏覽:416
電子書app怎麼上傳 瀏覽:66
國家反詐中心app注冊怎麼開啟 瀏覽:804
全波差分傅里葉演算法窗長 瀏覽:41
程序員如何講自己做過的項目 瀏覽:7
程序員要看的書頸椎 瀏覽:946
php文章cms 瀏覽:553
CSS權威指南第三版PDF 瀏覽:496
android怎麼搭建框架 瀏覽:184
正宗溯源碼大燕條一克一般多少錢 瀏覽:917