亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

Chinaunix

標(biāo)題: 月經(jīng)結(jié)貼 -- 《Segmentation Fault in Linux》 [打印本頁]

作者: zx_wing    時(shí)間: 2009-12-21 17:23
標(biāo)題: 月經(jīng)結(jié)貼 -- 《Segmentation Fault in Linux》
寫在前面的話
    最近CU(chinaunix)出現(xiàn)了很多問segmentation fault的帖子,其實(shí)這也是個(gè)“月經(jīng)貼”了,泡CU幾年,每個(gè)月都有人問。為了減少重復(fù)回帖,筆者結(jié)合自己的經(jīng)驗(yàn),總結(jié)了SIGSEGV在Linux中產(chǎn)生的機(jī)理,并用實(shí)際例子概括哪些編程錯(cuò)誤容易引發(fā)SIGSEGV。由于本人經(jīng)驗(yàn)有限,文中難免有疏漏和錯(cuò)誤,請發(fā)現(xiàn)的朋友發(fā)信到xing5820@163.com指正,筆者好即使修改。

內(nèi)容提要
  本文簡單介紹了Segmentation fault發(fā)生的原因,結(jié)合實(shí)際例子描述了內(nèi)核向用戶態(tài)程序發(fā)送SIGSEGV信號的流程。文中以實(shí)例回答了常見的一些SIGSEGV問題,例如“為什么函數(shù)返回了棧還可以訪問?”、“為什么free()后的內(nèi)存仍然可以使用”、“為什么我遇到的是SIGSEGV而不是SIGILL信號”等。最后筆者結(jié)合自己的經(jīng)驗(yàn),列舉了一些預(yù)防SIGSEGV的編程習(xí)慣,供大家參考。SIGSEGV嚴(yán)格依賴操作系統(tǒng)、編譯器、硬件平臺,本文基于Linux、GCC、32bit IA32架構(gòu),但對其他平臺操作系統(tǒng)也有借鑒意義。


大家在閱讀的過程中發(fā)現(xiàn)什么錯(cuò)誤,或我沒有講到的segfault情況,請及時(shí)指出,我好更正。

Segmentation fault in Linux.pdf

309.26 KB, 下載次數(shù): 4418


作者: unistd    時(shí)間: 2009-12-21 17:28
下來看看。。。
作者: OwnWaterloo    時(shí)間: 2009-12-21 17:28
標(biāo)題: 回復(fù) #1 zx_wing 的帖子
沙發(fā)居然被 …… 搶了……
留名
作者: OwnWaterloo    時(shí)間: 2009-12-21 17:39
標(biāo)題: 回復(fù) #1 zx_wing 的帖子
看了一下……  看來那帖子我是白費(fèi)口水了……
表面上說接受, 實(shí)際上依然是在鼓勵大家編寫不可移植代碼 —— 而且, 并不是為了得到什么實(shí)際的好處。
作者: cookis    時(shí)間: 2009-12-21 17:58
當(dāng)你的一個(gè)需求,標(biāo)準(zhǔn)的方法不能滿足時(shí),只有兩種可能:
1.從一開始的設(shè)計(jì)就錯(cuò)了,才會導(dǎo)致錯(cuò)誤的需求;
2.你讀過的代碼太少,不知道業(yè)界解決該問題的標(biāo)準(zhǔn)方法是什么。
作者: zx_wing    時(shí)間: 2009-12-21 18:04
原帖由 OwnWaterloo 于 2009-12-21 17:39 發(fā)表
看了一下……  看來那帖子我是白費(fèi)口水了……
表面上說接受, 實(shí)際上依然是在鼓勵大家編寫不可移植代碼 —— 而且, 并不是為了得到什么實(shí)際的好處。

哈哈哈,我是接受你看問題的角度,其它的我持保留意見。
至于這篇文章嘛,已經(jīng)不在標(biāo)準(zhǔn)范疇了,我一開始也說,這是非常平臺相關(guān)的
作者: albcamus    時(shí)間: 2009-12-21 18:13
樓主應(yīng)該寫書啊, 做獨(dú)立技術(shù)寫作也不錯(cuò)…
作者: OwnWaterloo    時(shí)間: 2009-12-21 18:18
標(biāo)題: 回復(fù) #6 zx_wing 的帖子
char a[] = "hello";
char* p;

for ( p = a+sizeof(a)-2; p>=a; p-- )
      printf("%c\n", *p );

與:

for ( p = a+sizeof(a)-2; p!=a; p-- )
      printf("%c\n", *p );


效果是一樣的: 如果真出現(xiàn)那帖里的情況, 不會越界,不會引發(fā)signal, 而是死循環(huán)。



上面2個(gè)版本與下面一個(gè)版本相比:

for ( p = a+sizeof(a)-1; p!=a /* or p>=a */; ) {
      --p;
      printf("%c\n", *p );
}

得到的好處就是 : 少寫一行代碼。  就為了這么點(diǎn)好處值得將代碼變得不可移植么?
如果推薦下面一種寫法, 什么煩惱都沒有了, 比如不需要補(bǔ)充這么一句:
筆者無法100%保證,所以大家在實(shí)踐中還是各自斟酌吧。



當(dāng)然,會出現(xiàn)回繞的機(jī)器只是假象出來的, 也許下面一種寫法的好處永遠(yuǎn)得不到。
我只是反感這么一種風(fēng)氣: 將自己的實(shí)踐、 不經(jīng)過嚴(yán)格的論證, 就上升到理論高度, 認(rèn)為那是普遍真理。
我真的不是在說你,  你的文章里至少還有那么一句補(bǔ)充說明, 以說明這種經(jīng)驗(yàn)的適用范圍。
我其實(shí)說的是林銳…… 以及和林銳有相同傾向的一幫人……


算了, 別人寫的代碼是否可移植關(guān)我鳥事 ……   大家愛怎么寫就怎么寫好了……

[ 本帖最后由 OwnWaterloo 于 2009-12-21 18:20 編輯 ]
作者: zx_wing    時(shí)間: 2009-12-21 18:35
原帖由 albcamus 于 2009-12-21 18:13 發(fā)表
樓主應(yīng)該寫書啊, 做獨(dú)立技術(shù)寫作也不錯(cuò)…

哈哈哈,哪兒有那功夫,平時(shí)忙的要死,泡個(gè)論壇都是忙里偷閑了。
上次不是chen xu過來提到說我泡CU,我差不多都要忘了有好久沒上過了。
寫書真是吃力不討好的事情,就那本在內(nèi)核版打廣告的書,我雖然只寫了一章加一節(jié),但被老板當(dāng)較字工人讓去review全書,那真是一個(gè)字一個(gè)字得看,一個(gè)字一個(gè)字的改啊,慘的不行。發(fā)現(xiàn)錯(cuò)誤還要去請教那些大牛原意是什么的,然后幫他們重寫。還是寫點(diǎn)這種小文好了,全憑興趣,想怎么寫就怎么寫
中國人搞技術(shù)啊,真是為了討生活,除非像老外衣食無憂純粹的"working for fun"差不多。
作者: lenky0401    時(shí)間: 2009-12-21 18:45
先頂貼再看文章是lenky的一貫作風(fēng)。
作者: zx_wing    時(shí)間: 2009-12-21 18:53
原帖由 OwnWaterloo 于 2009-12-21 18:18 發(fā)表
char a[] = "hello";
char* p;

for ( p = a+sizeof(a)-2; p>=a; p-- )
      printf("%c\n", *p );

與:

for ( p = a+sizeof(a)-2; p!=a; p-- )
      printf("%c\n", *p );


效果是一樣的: 如 ...

嘿嘿,我理解你的意思,覺得標(biāo)準(zhǔn)都規(guī)定了好了,為什么就不好好按標(biāo)準(zhǔn)寫呢。
這里面一是有歷史原因,一是不方便。
比如你這里這個(gè)例子
for ( p = a+sizeof(a)-1; p!=a /* or p>=a */; ) {
      --p;
      printf("%c\n", *p );
}
先--p就把空字符去掉了,很可能別人原意就要打印這個(gè)空字符。p!=a,又少打一個(gè)h,所以我在寫這個(gè)例子時(shí)都是跳出循環(huán)后再打一次。
標(biāo)準(zhǔn)規(guī)定的是完美情況,但現(xiàn)實(shí)中要想寫出完美的代碼時(shí)很難的,所以我說有一些既成事實(shí)的標(biāo)準(zhǔn)。比如說按標(biāo)準(zhǔn)寫:
int a = 70000;
嚴(yán)格來說這樣寫是不對的,因?yàn)椴恢肋@個(gè)int的長度,如果是2字節(jié),它就溢出了。怎么辦呢,寫成
int32_t a = 70000;
是保險(xiǎn)的。這意味著我們就不隨便使用int、short、long之類的變量的,一定要#include <stdint.h>。但那么多的教材、那么多的書籍都在這樣用,
從一學(xué)C語言就開始這樣用,突然就告訴說這樣不對,不嚴(yán)格,在某些情況下會出錯(cuò)。但實(shí)際上99%的時(shí)間我們寫不是跨平臺程序,要把所有細(xì)節(jié)都嚴(yán)格按照標(biāo)準(zhǔn),
基本上就寸步難行了。所以對于這種情況,人們大都follow的那些即成事實(shí)的標(biāo)準(zhǔn)。也正是因?yàn)橛羞@些既成事實(shí)的標(biāo)準(zhǔn)了,所以幾乎也不會出現(xiàn)你說那種特殊的編譯器,出現(xiàn)了也不會被市場接受。

歷史原因也有很多,比如大家都知道宏不好,定義常量會污染名字空間,應(yīng)該用enum。寫函數(shù)沒有類型檢查,應(yīng)該用inline函數(shù)。但它就用了這么久了,那么多知名項(xiàng)目都在用,都這樣用,所以也有很多人follow。

OwnWaterloo你可能是個(gè)追求完美的人,但現(xiàn)實(shí)中大部分時(shí)候都不是完美的。我倒不是鼓勵大家不遵守標(biāo)準(zhǔn),我只是從我的觀點(diǎn)陳述一種事實(shí),即它可能不符合標(biāo)準(zhǔn),但它99%的時(shí)間不會出錯(cuò),至于如何抉擇,就看個(gè)人了。

>>算了, 別人寫的代碼是否可移植關(guān)我鳥事 ……   大家愛怎么寫就怎么寫好了……
至于這個(gè)嘛,你也別急,現(xiàn)實(shí)中和別人意見相左的情況很多,其實(shí)我們只要了解了別人的觀點(diǎn),理解他的出發(fā)點(diǎn),然后在心中堅(jiān)持自己的理念即可。至于別人怎么做怎么想,那真是管我們鳥事
作者: OwnWaterloo    時(shí)間: 2009-12-21 19:15
標(biāo)題: 回復(fù) #11 zx_wing 的帖子
我是故意把空字符去掉的……   上面2份代碼是-2 ……
要輸出空字符的話:
for ( p = a+sizeof(a)/*-1 把這個(gè)-1去掉*/; p!=a /* or p>=a */; ) {
      --p;
      printf("%c\n", *p );
}

那么, 在逆向遍歷這個(gè)問題上, 遵守標(biāo)準(zhǔn)的寫法, 還會造成什么不方便么?
如果還有, 請指出, 再討論有沒有可以遵守標(biāo)準(zhǔn)也能寫出的方法。

其實(shí), 多出的那一行也是可以去掉的……  只是……   我寫了你就明白只是什么了……
for (T* p = a + n; p!=a; )
      --p, process( *p );


事實(shí)標(biāo)準(zhǔn)確實(shí)重要。 現(xiàn)實(shí)生活中其實(shí)依賴的是事實(shí)標(biāo)準(zhǔn)。 我的觀點(diǎn)是: 不應(yīng)該沒有任何理由地、 無故地違反標(biāo)準(zhǔn)
所以遇見這種問題, 我一般都先問case。 而不是說"一定不能那樣做"。
如果標(biāo)準(zhǔn)能解決這個(gè)case, 那還有什么理由去依賴未定義行為呢?
如果標(biāo)準(zhǔn)不能, 或者不夠高效(也算是不能), 這種情況我自己都會去違反標(biāo)準(zhǔn)……



關(guān)于那個(gè)帖里22樓的那種yin 蕩的、會主動crash程序的C實(shí)現(xiàn), 我又想了想, 應(yīng)該只會出現(xiàn)在想象中, 而不會實(shí)際出現(xiàn)。
因?yàn)檫@不符合C的邏輯 —— C語言是不會做多余的事情以提供保姆功能的。
但underflow確實(shí)是有可能的。 這依然是因?yàn)镃語言的邏輯 —— 不會做多余的事情以提供保姆功能 —— 檢查offset的溢出并相應(yīng)的修改segment就是一種多余的保姆功能。

所以, 逆向遍歷的case, 這么寫也應(yīng)該沒問題 —— 在正常的C編譯器上:
for (T* p = a + n; p-- != a; )
      process( *p );

有可能溢出, 但正常的C編譯器不會提供檢測溢出并且crash程序的功能。
熟悉msvc的同學(xué)說話前先仔細(xì)看清楚了: 這里的溢出僅僅是算術(shù)運(yùn)算的溢出, 并沒有到溢出的單元。/RTCs檢查的不是這種情況。
如果真有檢查算術(shù)溢出的C編譯器 ……  我相信沒人會去用的。
作者: zx_wing    時(shí)間: 2009-12-21 19:25
原帖由 OwnWaterloo 于 2009-12-21 19:15 發(fā)表
我是故意把空字符去掉的……   上面2份代碼是-2 ……
要輸出空字符的話:
for ( p = a+sizeof(a)/*-1 把這個(gè)-1去掉*/; p!=a /* or p>=a */; ) {
      --p;
      printf("%c\n", *p );
}

那么, 在逆 ...

是我看錯(cuò)了,你把 --p提出來了。

這樣是很好,但一般人不會相到這樣寫。就像你后來說了,人們不會接受指針?biāo)阈g(shù)溢出會導(dǎo)致錯(cuò)誤。

[ 本帖最后由 zx_wing 于 2009-12-21 19:29 編輯 ]
作者: OwnWaterloo    時(shí)間: 2009-12-21 19:29
標(biāo)題: 回復(fù) #13 zx_wing 的帖子
當(dāng)真?
作者: zx_wing    時(shí)間: 2009-12-21 19:30
原帖由 OwnWaterloo 于 2009-12-21 19:29 發(fā)表
當(dāng)真?

你回的真快,我剛改你就回了。見上
作者: OwnWaterloo    時(shí)間: 2009-12-21 19:35
標(biāo)題: 回復(fù) #13 zx_wing 的帖子
原帖由 zx_wing 于 2009-12-21 19:25 發(fā)表
就像你后來說了,人們不會接受指針?biāo)阈g(shù)溢出會導(dǎo)致錯(cuò)誤。

人們不會接受的是編譯器主動檢查溢出而導(dǎo)致錯(cuò)誤。

因?yàn)榫幾g器沒有檢測溢出而導(dǎo)致的語意錯(cuò)誤, 是程序員的責(zé)任。
作者: OwnWaterloo    時(shí)間: 2009-12-21 19:42
標(biāo)題: 回復(fù) #13 zx_wing 的帖子
原帖由 zx_wing 于 2009-12-21 19:25 發(fā)表
但一般人不會相到這樣寫


用idx逆向遍歷 —— 自從某次錯(cuò)誤之后 —— 我都是這么寫的
for (size_t idx = size; idx-- ; )
      process( a[idex] );


用prt逆向遍歷……  也是在那個(gè)帖里才頭一次考慮這個(gè)問題, 以后我會選擇:
for (T* ptr = a + size; ptr != a; ) {
      --ptr;
      process( *ptr );
}

for (T* ptr = a + size; ptr-- != a; )
      process( *ptr );

for (T* ptr = a + size; ptr != a; )
      --ptr, process( *ptr );


之一
作者: happyzlz    時(shí)間: 2009-12-21 22:54
原帖由 zx_wing 于 2009-12-21 18:53 發(fā)表

嘿嘿,我理解你的意思,覺得標(biāo)準(zhǔn)都規(guī)定了好了,為什么就不好好按標(biāo)準(zhǔn)寫呢。
這里面一是有歷史原因,一是不方便。
比如你這里這個(gè)例子
for ( p = a+sizeof(a)-1; p!=a /* or p>=a */; ) {
      --p;
    ...


我做嵌入式開發(fā)比較多,為了能夠在16位機(jī)和32位機(jī)之間更好的移植,代碼中的 int 都會寫成 int32_t 這樣子的。
作者: happyzlz    時(shí)間: 2009-12-21 22:57
標(biāo)題: 回復(fù) #1 zx_wing 的帖子
最近我也出了一系列段錯(cuò)誤,其中一個(gè)比較深刻,大意如下:???標(biāo)示不用關(guān)注。
...
struct ??? * x = malloc( ??? );
char * p = x->data;
x = realloc( x , ??? );
??? = *p;

[ 本帖最后由 happyzlz 于 2009-12-21 23:08 編輯 ]
作者: axlrose    時(shí)間: 2009-12-22 10:58
好文章,收藏,傳閱
作者: file3    時(shí)間: 2009-12-22 11:07
超級喜歡短錯(cuò)誤
作者: gofortime    時(shí)間: 2009-12-22 11:46
來看zx_wing和OwnWaterloo辯論,
作者: OwnWaterloo    時(shí)間: 2009-12-22 14:39
標(biāo)題: 回復(fù) #19 happyzlz 的帖子
這個(gè)錯(cuò)誤可以歸類

hanlde何時(shí)失效

0. happyzlz列舉的p

1. vector,
vector<T> v = ...
T* p = &v[ 0 ];
vector<T>::iterator it = v.begin();
v.push_back( xxx );  

2. string
string s = ...
const char* p = s.c_str();
s = xxx;   

3. ctime  asctime
char* s = ctime( time(0) );
ctime( time(0) );
作者: zhyclt    時(shí)間: 2009-12-22 16:01
原帖由 zx_wing 于 2009-12-21 18:35 發(fā)表

哈哈哈,哪兒有那功夫,平時(shí)忙的要死,泡個(gè)論壇都是忙里偷閑了。
上次不是chen xu過來提到說我泡CU,我差不多都要忘了有好久沒上過了。
寫書真是吃力不討好的事情,就那本在內(nèi)核版打廣告的書,我雖然只寫了 ...

最后一句說的好啊,中國人做技術(shù),純屬討生活
作者: koolcoy    時(shí)間: 2009-12-22 16:12
其實(shí)sf的原因簡單的歸結(jié)一下就是:
讀了,寫了或者執(zhí)行了 不該讀, 不該寫或者不該執(zhí)行的內(nèi)存。
作者: to407    時(shí)間: 2009-12-22 18:17
下了不看,繼續(xù)加班
作者: mik    時(shí)間: 2009-12-22 20:24
zx_wing 花了不少心思啊

zx_wing 把你寫過的專集再添加、整理、修飾、校對一下,可以出書了。

至少比市面上某些作者好多了。
作者: zx_wing    時(shí)間: 2009-12-22 21:38
原帖由 mik 于 2009-12-22 20:24 發(fā)表
zx_wing 花了不少心思啊

zx_wing 把你寫過的專集再添加、整理、修飾、校對一下,可以出書了。

至少比市面上某些作者好多了。

老大過獎了
寫過的東西還不多。反正憑興趣,寫點(diǎn)小東西,集多了也是件有成就感的事情
作者: leiing    時(shí)間: 2009-12-23 08:53
好文章,學(xué)習(xí)中
作者: 登樓望月    時(shí)間: 2009-12-23 10:11
學(xué)習(xí),謝謝lz
作者: coneagoe    時(shí)間: 2009-12-23 12:29
看節(jié)選更像是寫的論文.mark
作者: deargodzw    時(shí)間: 2009-12-23 13:41
經(jīng)典分析總結(jié),看完了,受益匪淺
作者: rainballdh    時(shí)間: 2009-12-23 17:19
拜讀以下,謝謝
作者: it-rocket    時(shí)間: 2009-12-23 22:12
好東西,樓主辛苦了!
作者: 灰菲湮滅    時(shí)間: 2009-12-24 09:47
樓主辛苦,下下來看看~~
作者: skybyte    時(shí)間: 2009-12-24 10:12
標(biāo)題:
c = (char*)&c – 8192 *2;
這句話是什么意思
優(yōu)先級是不是這樣
( (char*)&c) – 8192 *2;
感覺這個(gè)很怪樣,把指針地址當(dāng)成c的地址值再減去8192*2

c=c-8192*2; 直接這樣也會出錯(cuò)啊

[ 本帖最后由 skybyte 于 2009-12-24 10:34 編輯 ]
作者: skybyte    時(shí)間: 2009-12-24 10:31
標(biāo)題: warning
a = malloc (sizeof(int));
會出現(xiàn)
tree.c(5) : warning C4133: '=' : incompatible types - from 'char *' to 'int *'
沒加類型
a = (int*) malloc (sizeof(int));
作者: waily    時(shí)間: 2009-12-24 11:41
好文 謝謝!
作者: silentfish    時(shí)間: 2009-12-24 13:08
印證了以前我不確認(rèn)的觀點(diǎn),學(xué)習(xí)了一些新的東西,糾正了一些以前的認(rèn)識錯(cuò)誤
非常感謝!

[ 本帖最后由 silentfish 于 2009-12-24 13:26 編輯 ]
作者: qiang1012    時(shí)間: 2009-12-24 17:26
收藏了,謝謝樓主~~~
作者: towel    時(shí)間: 2009-12-24 23:19
大概看了一邊,如果說是對于初學(xué)者來說,有點(diǎn)不適合.
作者: nice90    時(shí)間: 2009-12-25 11:15
不錯(cuò),我轉(zhuǎn)發(fā)給了同事們。
segmentation fault經(jīng)常出現(xiàn)在C++中,大家實(shí)在是對臨時(shí)對象和生成對象管理不嚴(yán)格。
作者: kenshinxf    時(shí)間: 2009-12-26 15:57
前一段日子還和同事一起總結(jié)了呢
呵呵
作者: angle4    時(shí)間: 2009-12-26 16:27
還沒看內(nèi)容,但樓主的精神首先很贊
作者: Tim_tsang    時(shí)間: 2009-12-26 16:43
標(biāo)題: 回復(fù) #1 zx_wing 的帖子
佩服,熱血沸騰。。。
作者: tianxiaogang12    時(shí)間: 2009-12-27 16:16
在下水平有限,請問
在build_ill_func函數(shù)里面的if ( buf == 0xffffffe8 )語句中的
          0xffffffe8是指什么, 是文章中說的call指令嗎? 具體講講貝
作者: gpp9837    時(shí)間: 2009-12-28 18:01
支持樓主工作。。!
作者: ppyyf    時(shí)間: 2010-01-15 10:41
這些東西直接在帖子里寫寫不就好了嗎?用得著要放到PDF作為附件下載嗎?
作者: thyman    時(shí)間: 2010-01-18 16:33
不錯(cuò)不錯(cuò)!
作者: kofshower    時(shí)間: 2010-05-18 10:51
下來看看,這只是內(nèi)存錯(cuò)誤的一種,呵呵,希望有系列文檔
作者: gigabyte    時(shí)間: 2010-05-18 14:25
支持……
作者: BMW_325i    時(shí)間: 2010-05-23 15:11
看樣子應(yīng)該是好東西,先收藏了
作者: rain_fish    時(shí)間: 2010-05-23 19:57
lz好樣的。。。
作者: zhuqing_739    時(shí)間: 2010-09-19 12:44
這是一個(gè)曾今遇到過的問題。。。。!
作者: aaron_xueli    時(shí)間: 2010-09-24 16:12
新手學(xué)習(xí)中……,分享,謝謝樓主!
作者: whuhujin    時(shí)間: 2010-12-26 13:10
回復(fù) 1# zx_wing


    呵呵,多謝分享哦
作者: nju_chenbin    時(shí)間: 2011-05-23 10:55
多謝多謝了餓啊
作者: zhuyoong    時(shí)間: 2011-07-01 14:51
先頂再看。
作者: emwoody    時(shí)間: 2012-10-26 15:26
下來看看,先頂了!
作者: ly20119    時(shí)間: 2012-11-05 19:03
好東西
作者: zeorro    時(shí)間: 2012-11-18 19:10
mark,最近對 segmentation fault 怕的。。
作者: flfromhlp    時(shí)間: 2014-08-22 12:26
下來看看有哪些原因會產(chǎn)生這個(gè)錯(cuò)誤




歡迎光臨 Chinaunix (http://www.72891.cn/) Powered by Discuz! X3.2