要談segment fault,必需要談指針。程序員
指針的本質是什麼?只不過是一種帶*的數據類型,其特點有:指針
一、寬度ip
二、聲明內存
三、賦值變量
四、++與--cli
五、+與-file
六、求差值數據類型
七、比較程序
當聲明int *ptr = 0x0以後,ptr1就是一個指針變量了,im
能夠對ptr1作++,--,+,-等各類操做,
然而不能訪問ptr地址中的內容,由於訪問的是非法內存地址0x0(內核空間地址?)。
當聲明int *prt2 = 0x12345678以後,prt2就是一個指針變量了,
能夠對ptr1作++,--,+,-等各類操做,
也能夠訪問ptr地址中的內容,由於訪問的是合法內存地址0x12345678(用戶空間地址)。
從Linux內核角度來看,segment fault發生有三種緣由:
當應用程序訪問一個虛擬地址時,正常狀況下,你其實是在訪問處於某個VMA中的一個地址而已。若是你正常的訪問,那麼一切都如你所願,MMU讀入內核task_struct中記錄的表格,而後,虛擬地址正確地轉換到物理內存地址。可是,若是: 1. 若是內核標明這個VMA是隻讀的,但你恰恰往這個地址段中寫,內核天然不能容忍應用程序犯這樣的錯誤。2. 你可能去訪問虛擬地址空間中某個根本沒有映射的hole. 剛學指針的 C 程序員老是覺得本身無所不能,好比:int *p = (int *)0x543;*p = 5;而後運行程序時,他確定會很開心地收到段錯誤,而後爲此鬱悶一個下午。究其緣由其實很簡單: 0x543這個地址沒有處於一個合法的VMA中,它可能處於一個根本沒有和物理內存映射的虛擬空間的hole中. 對於教訓新手 C 程序員來講,內核仍是很是樂意的,由於新手C程序員離可以駕馭Linux內核的水準至少還差那麼三五年時間。3. 應用程序訪問內核空間(0xc000 0000 --> 0xffff ffff),內核早早就說明那不是應用程序應該訪問的地址範圍。竟然敢打內核的主意!這個應用程序必定活得很是不耐煩,是在找抽。