C语言段错误的有用总结
例題:
有以下兩個文件,輸出結果是 ()
文件A:
int a[10] = {100};
文件B:
#include <stdio.h>
extern int *a;
void main()
{
????printf("%d", a[0]);
}
A) 100???B)?0???C) 段錯誤???D)?編譯錯誤
測試結果:
????
解釋:
在extern int *a和printf("%d", a[0])這兩條語句中,編譯器覺得a是一個指針變量,所以它提取存儲在那里的指針值,然后對這個結果運行間接訪問操作。但a實際上是整型數組的起始位置,所以作為"指針"獲得的這個值實際上是數組的第一個整形元素。其結果解釋為一個地址。然后對它進行間接訪問。作為結果,它或者將提取一些隨意內存位置的內容。或者因為某種地址錯誤而導致程序失敗。
段錯誤的常見原因總結:
一、段錯誤究根到底就是訪問了非法內存
這個內存區要么是不存在的,要么 是受到系統保護的,還有可能是缺少文件或者文件損壞。可能的原因包括:
訪問代碼段(原因經常是指針未初始化指向了錯誤的位置或解引用空指針)、訪問寄存器
例子1:解引用空指針 int *p=NULL; printf("%d\n",*p); //因為內存低地址為代碼段,不可訪問
例子2:訪問含有非法值得內存 register int p =10; printf("%d\n",*p); //由于register關鍵字使變量存儲到內核寄存器中,因此不能訪問
野指針:即定義指針時并未對其初始化,其指向的的位置式未知的。對野指針解引用可能造成段錯誤或者導致程序崩潰
防止方案:1;定義時初始化為NULL 2;解引用前賦值 3;使用完后指向NULL 每次使用指針之前記得賦值就好了
二、數組越界
如:當使用malloc申請了一頁內存,但使用卻超出了。 越過數組邊界寫入數據,在動態分配的內存兩端之外寫入數據,或改寫一些堆管 理數據結構(在動態分配的內存之前的區域寫入數據)
堆中:p = malloc(256); p[-1] = 0; p[256] = 0; //訪問了未知空間的內存
棧中:int *p=NULL; int a[6]; p=a; for(int i=0;i<10;i++){*p++=i;} //stack smashing detected 訪問了未知空間的內存
三、scanf錯誤使用
int b;?
scanf("%d",b);//應為scanf("%d",&b);
四、指針訪問只讀內存區
如:char *p=“abcddf”; *p=‘A’; //其實本質上錯誤原因和解引用空指針類似,“abcddf”在被定義時放在了代碼段或常量區。
//解決方法是將字符串存到數組中,再將指針指向數組頭
這里補充一下程序運行時內存分配:
1 棧區:存放函數運行時產生的臨時變量,局部變量、函數的入口參數,返回值和const定義的局部變量,函數結束后由編譯器釋放。
2 堆區:用于存放程序運行時被動態分配的內存段,一般由程序員手動申請釋放malloc申請,free釋放。
3 全局區(靜態區):全局區用來存儲全局變量,主要分為兩個段:1. .bss段:該段用于存放未初始化或者初始化為0的全局變量和靜態變量(static)
2. .data段:又叫數據段,用于存儲初始化不為0的全局變量和靜態變量、const定義的全局變量(在.rodata段)
該段在程序結束后由系統釋放。
4 常量區:常量字符串就是放在這里的。 程序結束后由系統釋放
5 代碼區:又叫.text段用于存放函數的代碼,部分字符串常量也存在代碼段
三個申請內存的函數:
1. void *malloc(unsigned int size); //單位為字節 如要申請200個字節的空間存儲int型數據 int *p=(int *)malloc(50 *sizeof(int))
2. void *calloc(unsigned n,unsigned size); //long *buffer; buffer =(long *)calloc(20,sizeof(long)); 獲得一塊長整型數組空間
3. void *realloc(void *mem_address,unsigned int newsize);//重新分配內存
三種方式,申請成功返回(void *)類型的指針,失敗返回NULL;使用完之后切記要free釋放
?
總結
以上是生活随笔為你收集整理的C语言段错误的有用总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux c 获取终端输出到文件,LI
- 下一篇: iptv错误代码2003什么意思_IPT