指針、結(jié)構(gòu)體、聯(lián)合體的安全規(guī)范
發(fā)布時(shí)間:2007/8/30 0:00:00 訪問(wèn)次數(shù):964
來(lái)源:?jiǎn)纹瑱C(jī)及嵌入式系統(tǒng)應(yīng)用 作者:清華大學(xué) 張樂(lè)平 邵貝貝
指針賦予了C編程最大的靈活性;結(jié)構(gòu)體使得C程序整齊而緊湊;聯(lián)合體在某些要求注重效率的場(chǎng)合有精彩的表現(xiàn),這三個(gè)要素是C語(yǔ)言的精華。
然而,精華并不意味著完美,C語(yǔ)言在賦予程序員足夠靈活性的同時(shí),也給了程序員很多犯錯(cuò)誤的機(jī)會(huì)。所以有必要關(guān)注指針、結(jié)構(gòu)體和聯(lián)合體的實(shí)現(xiàn)細(xì)節(jié),從而保障程序的安全性。
在此.第一部分介紹《MISRA—C:2004》中與指針相關(guān)的部分規(guī)則,第二部分講解結(jié)構(gòu)體和聯(lián)合體的操作規(guī)范。下文中凡是未加特殊說(shuō)明的都是強(qiáng)制(required)規(guī)則,個(gè)別推薦(advisory)規(guī)則加了“推薦”標(biāo)示。
1 指針的安全規(guī)范
《MISRA—C:2004》關(guān)于指針的規(guī)范主要分為三個(gè)部分:指針的類(lèi)型轉(zhuǎn)換規(guī)則、指針運(yùn)算的規(guī)則和指針的有效性規(guī)則。
1.1 指針的類(lèi)型轉(zhuǎn)換
指針類(lèi)型轉(zhuǎn)換是個(gè)高風(fēng)險(xiǎn)的操作,所以應(yīng)該盡量避免進(jìn)行這個(gè)操作。MISRA—C對(duì)其中可能造成嚴(yán)重錯(cuò)誤的情況作了嚴(yán)格的限定,選擇其中兩條作簡(jiǎn)要分析。
規(guī)則11.4(推薦):指向不同數(shù)據(jù)類(lèi)型的指針之間不能相互轉(zhuǎn)換。
思考如下程序:
uint8_t*pl;
uint32)_t*p2;
p2=(uint32_t*)pl;
/*注:uint8_t表示8位無(wú)符號(hào)整型,uint3_t表示32位無(wú)符號(hào)整型。*/
程序員希望將從p1單元開(kāi)始的4個(gè)字節(jié)組成一個(gè)32付的整型來(lái)參與運(yùn)算。
如果CPU允許各種數(shù)據(jù)對(duì)象存放在任意的存儲(chǔ)單元,則以上轉(zhuǎn)換沒(méi)有問(wèn)題。但某些CPU對(duì)某種(些)數(shù)據(jù)類(lèi)型加強(qiáng)了對(duì)齊限制,要求這些數(shù)據(jù)對(duì)象占用一定的地址空間,比如某些字節(jié)尋址的CPU會(huì)要求32位(4字節(jié))整型存放在4的整倍數(shù)地址上。在這個(gè)前提下.思考程序中的指針轉(zhuǎn)換:假設(shè)pl一開(kāi)始指向的是0x00O3單元(對(duì)uint8_t型的整型沒(méi)有對(duì)齊要求),則執(zhí)行最后一行強(qiáng)制轉(zhuǎn)換后,p2到底指向哪個(gè)單元就無(wú)法預(yù)料了。
規(guī)則1 1.5:指針轉(zhuǎn)換過(guò)程中不允許丟失指針的const、volatile屬性。按如下定義指針:
uIntl6一tx;
uint16_t*const cpi=&x; /*const指針*/
uintl6_t*const *pcpi;/*指向const指針的指針*/
const uintl6_t* *ppci;/*指向const整型指針的指針*/
uIntl6_t**ppi ;
const uint16_t *pci;/*指向const整型的指針*/
volatik uint16_t*pvi;/*指向volatile整型的指針*/
uintl6_t*pi;
則以下指針轉(zhuǎn)換是允許的:
pl=cpi;
以下指針轉(zhuǎn)換是不允許的:
pi=(umtl6_t*)pci;
pi=(uintl6_t*)pvil
ppi=(uintl6_t* *)pcpi;
ppi=(uintl6_I**)ppci+
以上非法指針類(lèi)型轉(zhuǎn)換將會(huì)丟失const或者volatile類(lèi)型。丟失const屬性,將有可能導(dǎo)致在對(duì)只讀內(nèi)容進(jìn)行寫(xiě)操作時(shí),編譯器不會(huì)發(fā)出警告,編譯器將不對(duì)具有volatile屬性的變量作優(yōu)化;丟失volatile屬性,編譯器的優(yōu)化可能導(dǎo)致程序員預(yù)先設(shè)計(jì)的硬件時(shí)序操作失效,這樣的錯(cuò)誤很難發(fā)現(xiàn)。關(guān)于const和volatile關(guān)鍵字的詳細(xì)作用,讀者可參考ISOC獲取更多信息。
1.2 指針的運(yùn)算
ISOC標(biāo)準(zhǔn)中,對(duì)指向數(shù)組成員的指針運(yùn)算(包括算術(shù)運(yùn)算、比較等)做了規(guī)范定義,除此以外的指針運(yùn)算屬于未定義(undefined)范圍,具體實(shí)現(xiàn)有賴(lài)于具體編譯器,其安全性無(wú)法得到保障,MISRA—C中對(duì)指針運(yùn)算的合法范圍做了如下限定。
規(guī)則17.1:只有指向數(shù)組的指針才允許進(jìn)行算術(shù)運(yùn)算①。
規(guī)則17 2:只有指向同一個(gè)數(shù)組的兩個(gè)指針才允許相減 ②。
規(guī)則17 3:只有指向同一個(gè)數(shù)組的兩個(gè)指針才允許用>,>=,<,<=等關(guān)系運(yùn)算符進(jìn)行比較。
為了盡最大可能減少直接進(jìn)行指針運(yùn)算帶來(lái)的隱患,尤其是程序動(dòng)態(tài)運(yùn)行時(shí)可能發(fā)生的數(shù)組越界等問(wèn)題,MISRA—C對(duì)指針運(yùn)算作了更為嚴(yán)格的規(guī)定。規(guī)則17 4:只允許用數(shù)組索引做指針運(yùn)算。按如下方式定義數(shù)組和指針:
uint8_ta[10];
uint8_t*p;
則*(p+5)=O是不允許的.而p[5]=O則是允許的,盡管就這段程序而言,二者等價(jià)。
以下給出一段程序,讀者可參照相應(yīng)程序行的注釋?zhuān)?xì)細(xì)品味上述規(guī)則的含義。
void my_fn(uInt*_t*p1.uint8_t p2[]){
①其實(shí)此處的算術(shù)運(yùn)算僅限定于指針加減某個(gè)整數(shù).比如ppoint=point一5.ppoint++等。0兩個(gè)指針可指向不同的散組成員。
uint8_t index=0;
uint8_t*p3
uint8_t*p4;
*pl=O;
p1++;/*不允許,pl不是指向數(shù)組的指針*/
p1=p1+5;/*不允許,pl不是指向數(shù)組的指針*/
pl[5]=O;&
來(lái)源:?jiǎn)纹瑱C(jī)及嵌入式系統(tǒng)應(yīng)用 作者:清華大學(xué) 張樂(lè)平 邵貝貝
指針賦予了C編程最大的靈活性;結(jié)構(gòu)體使得C程序整齊而緊湊;聯(lián)合體在某些要求注重效率的場(chǎng)合有精彩的表現(xiàn),這三個(gè)要素是C語(yǔ)言的精華。
然而,精華并不意味著完美,C語(yǔ)言在賦予程序員足夠靈活性的同時(shí),也給了程序員很多犯錯(cuò)誤的機(jī)會(huì)。所以有必要關(guān)注指針、結(jié)構(gòu)體和聯(lián)合體的實(shí)現(xiàn)細(xì)節(jié),從而保障程序的安全性。
在此.第一部分介紹《MISRA—C:2004》中與指針相關(guān)的部分規(guī)則,第二部分講解結(jié)構(gòu)體和聯(lián)合體的操作規(guī)范。下文中凡是未加特殊說(shuō)明的都是強(qiáng)制(required)規(guī)則,個(gè)別推薦(advisory)規(guī)則加了“推薦”標(biāo)示。
1 指針的安全規(guī)范
《MISRA—C:2004》關(guān)于指針的規(guī)范主要分為三個(gè)部分:指針的類(lèi)型轉(zhuǎn)換規(guī)則、指針運(yùn)算的規(guī)則和指針的有效性規(guī)則。
1.1 指針的類(lèi)型轉(zhuǎn)換
指針類(lèi)型轉(zhuǎn)換是個(gè)高風(fēng)險(xiǎn)的操作,所以應(yīng)該盡量避免進(jìn)行這個(gè)操作。MISRA—C對(duì)其中可能造成嚴(yán)重錯(cuò)誤的情況作了嚴(yán)格的限定,選擇其中兩條作簡(jiǎn)要分析。
規(guī)則11.4(推薦):指向不同數(shù)據(jù)類(lèi)型的指針之間不能相互轉(zhuǎn)換。
思考如下程序:
uint8_t*pl;
uint32)_t*p2;
p2=(uint32_t*)pl;
/*注:uint8_t表示8位無(wú)符號(hào)整型,uint3_t表示32位無(wú)符號(hào)整型。*/
程序員希望將從p1單元開(kāi)始的4個(gè)字節(jié)組成一個(gè)32付的整型來(lái)參與運(yùn)算。
如果CPU允許各種數(shù)據(jù)對(duì)象存放在任意的存儲(chǔ)單元,則以上轉(zhuǎn)換沒(méi)有問(wèn)題。但某些CPU對(duì)某種(些)數(shù)據(jù)類(lèi)型加強(qiáng)了對(duì)齊限制,要求這些數(shù)據(jù)對(duì)象占用一定的地址空間,比如某些字節(jié)尋址的CPU會(huì)要求32位(4字節(jié))整型存放在4的整倍數(shù)地址上。在這個(gè)前提下.思考程序中的指針轉(zhuǎn)換:假設(shè)pl一開(kāi)始指向的是0x00O3單元(對(duì)uint8_t型的整型沒(méi)有對(duì)齊要求),則執(zhí)行最后一行強(qiáng)制轉(zhuǎn)換后,p2到底指向哪個(gè)單元就無(wú)法預(yù)料了。
規(guī)則1 1.5:指針轉(zhuǎn)換過(guò)程中不允許丟失指針的const、volatile屬性。按如下定義指針:
uIntl6一tx;
uint16_t*const cpi=&x; /*const指針*/
uintl6_t*const *pcpi;/*指向const指針的指針*/
const uintl6_t* *ppci;/*指向const整型指針的指針*/
uIntl6_t**ppi ;
const uint16_t *pci;/*指向const整型的指針*/
volatik uint16_t*pvi;/*指向volatile整型的指針*/
uintl6_t*pi;
則以下指針轉(zhuǎn)換是允許的:
pl=cpi;
以下指針轉(zhuǎn)換是不允許的:
pi=(umtl6_t*)pci;
pi=(uintl6_t*)pvil
ppi=(uintl6_t* *)pcpi;
ppi=(uintl6_I**)ppci+
以上非法指針類(lèi)型轉(zhuǎn)換將會(huì)丟失const或者volatile類(lèi)型。丟失const屬性,將有可能導(dǎo)致在對(duì)只讀內(nèi)容進(jìn)行寫(xiě)操作時(shí),編譯器不會(huì)發(fā)出警告,編譯器將不對(duì)具有volatile屬性的變量作優(yōu)化;丟失volatile屬性,編譯器的優(yōu)化可能導(dǎo)致程序員預(yù)先設(shè)計(jì)的硬件時(shí)序操作失效,這樣的錯(cuò)誤很難發(fā)現(xiàn)。關(guān)于const和volatile關(guān)鍵字的詳細(xì)作用,讀者可參考ISOC獲取更多信息。
1.2 指針的運(yùn)算
ISOC標(biāo)準(zhǔn)中,對(duì)指向數(shù)組成員的指針運(yùn)算(包括算術(shù)運(yùn)算、比較等)做了規(guī)范定義,除此以外的指針運(yùn)算屬于未定義(undefined)范圍,具體實(shí)現(xiàn)有賴(lài)于具體編譯器,其安全性無(wú)法得到保障,MISRA—C中對(duì)指針運(yùn)算的合法范圍做了如下限定。
規(guī)則17.1:只有指向數(shù)組的指針才允許進(jìn)行算術(shù)運(yùn)算①。
規(guī)則17 2:只有指向同一個(gè)數(shù)組的兩個(gè)指針才允許相減 ②。
規(guī)則17 3:只有指向同一個(gè)數(shù)組的兩個(gè)指針才允許用>,>=,<,<=等關(guān)系運(yùn)算符進(jìn)行比較。
為了盡最大可能減少直接進(jìn)行指針運(yùn)算帶來(lái)的隱患,尤其是程序動(dòng)態(tài)運(yùn)行時(shí)可能發(fā)生的數(shù)組越界等問(wèn)題,MISRA—C對(duì)指針運(yùn)算作了更為嚴(yán)格的規(guī)定。規(guī)則17 4:只允許用數(shù)組索引做指針運(yùn)算。按如下方式定義數(shù)組和指針:
uint8_ta[10];
uint8_t*p;
則*(p+5)=O是不允許的.而p[5]=O則是允許的,盡管就這段程序而言,二者等價(jià)。
以下給出一段程序,讀者可參照相應(yīng)程序行的注釋?zhuān)?xì)細(xì)品味上述規(guī)則的含義。
void my_fn(uInt*_t*p1.uint8_t p2[]){
①其實(shí)此處的算術(shù)運(yùn)算僅限定于指針加減某個(gè)整數(shù).比如ppoint=point一5.ppoint++等。0兩個(gè)指針可指向不同的散組成員。
uint8_t index=0;
uint8_t*p3
uint8_t*p4;
*pl=O;
p1++;/*不允許,pl不是指向數(shù)組的指針*/
p1=p1+5;/*不允許,pl不是指向數(shù)組的指針*/
pl[5]=O;&
熱門(mén)點(diǎn)擊
- 嵌入式系統(tǒng)內(nèi)存管理方案研究
- 指針、結(jié)構(gòu)體、聯(lián)合體的安全規(guī)范
- ARM內(nèi)核的中斷技術(shù)
- Microwindows在遠(yuǎn)程紅外抄表器中的
- 利用ColdFire uClinux實(shí)現(xiàn)數(shù)據(jù)
- 嵌入式Linux的動(dòng)態(tài)擴(kuò)展技術(shù)研究
- 采用8位單片機(jī)驅(qū)動(dòng)PCI總線網(wǎng)卡的設(shè)計(jì)方案
- 基于8051軟核的SOPC系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)
- 一款32位嵌入式CPU的定點(diǎn)加法器設(shè)計(jì)
- 嵌入式實(shí)時(shí)操作系統(tǒng)ECOS在S3C2510上
推薦技術(shù)資料
- 羅盤(pán)誤差及補(bǔ)償
- 造成羅盤(pán)誤差的主要因素有傳感器誤差、其他磁材料干擾等。... [詳細(xì)]
- CV/CC InnoSwitch3-AQ 開(kāi)
- URF1DxxM-60WR3系
- 1-6W URA24xxN-x
- 閉環(huán)磁通門(mén)信號(hào)調(diào)節(jié)芯片NSDRV401
- SK-RiSC-SOM-H27X-V1.1應(yīng)
- RISC技術(shù)8位微控制器參數(shù)設(shè)
- 多媒體協(xié)處理器SM501在嵌入式系統(tǒng)中的應(yīng)用
- 基于IEEE802.11b的EPA溫度變送器
- QUICCEngine新引擎推動(dòng)IP網(wǎng)絡(luò)革新
- SoC面世八年后的產(chǎn)業(yè)機(jī)遇
- MPC8xx系列處理器的嵌入式系統(tǒng)電源設(shè)計(jì)
- dsPIC及其在交流變頻調(diào)速中的應(yīng)用研究