一般如果c和c++中使用了指針編程,如果不注意使用,很容易出現segmentation錯誤,如果代碼中的錯誤日誌不夠的話,還在真不太方便定位,尤其是使用了大量指針的情況下。
網上總結的有下面幾條,我這裏摘抄一下
- 訪問了空指針:如
char* p;printf("%s\n", p);p指針沒有初始化分配內存空間,p的值一般爲0 NULL - 指針越界,實際也是訪問了空指針:int p[100];p[100]=1;
- 常量被修改
char *p = "abcd"; p[1]=e;
- 在一些比較老的操作系統上,非對齊訪問也可能導致segmentation fault
int
a[2];
char
*p1 = (
char
*)a;
//指向數組首地址。
int
*p2 = (
int
*)(p1+1);
//實際上將a[0]和a[1]的各一部分,組成了一個新的int。 這時對p2的訪問,包括讀寫,都屬於非對齊訪問。
*p2=3;
//此時有可能出現segmentation fault
還有一種情況,是在使用比較複雜的指針時會出現,如果結構體中含有指針,而本身結構體定義了一個指針變量,如果沒有執行清0步驟,結構體中的成員初始值將是不可預見的。
比如我的例子,在代碼中我定義瞭如下結構體,使用鏈表和遞歸來獲取xml文件所有節點的內容,引用了tinyxml.so庫
在用
tXmlNodeEntireDef * pNode = (tXmlNodeEntireDef *)malloc(sizeof(tXmlNodeEntireDef))
//沒有按照開發規範,使用meset進行初始化
memset(pNode, 0 ,sizeof(tXmlNodeEntireDef)
剛開始在xml簡單時沒有問題,但xml稍微複雜就上報錯誤:segmentation fault,中間打印了很多東西,最後把結構體變量中的
attriListNode的地址打印出來後才定位到,本來剛開始調用的應該是NULL,但卻莫名奇妙的有值,於是判斷到不等於NULL,就直接拿來用,實際這個值是不可用的,用了後導致上報segmentation fault ,訪問了非法地址
作爲初學走了不少彎路,以前實際也用過,每次都會按照規範memset一下,但這次就忘了,而且有時還認爲無關緊要
所以開發時一定要嚴格按照規範走!