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