日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 嵌入式 > 嵌入式教程
[導(dǎo)讀]指針、結(jié)構(gòu)體、聯(lián)合體的安全規(guī)范

    指針賦予了C編程最大的靈活性;結(jié)構(gòu)體使得C程序整齊而緊湊;聯(lián)合體在某些要求注重效率的場合有精彩的表現(xiàn),這三個(gè)要素是C語言的精華。


    然而,精華并不意味著完美,
C語言在賦予程序員足夠靈活性的同時(shí),也給了程序員很多犯錯(cuò)誤的機(jī)會。所以有必要關(guān)注指針、結(jié)構(gòu)體和聯(lián)合體的實(shí)現(xiàn)細(xì)節(jié),從而保障程序的安全性。


    在此.第一部分介紹《
MISRAC2004》中與指針相關(guān)的部分規(guī)則,第二部分講解結(jié)構(gòu)體和聯(lián)合體的操作規(guī)范。下文中凡是未加特殊說明的都是強(qiáng)制(required)規(guī)則,個(gè)別推薦(advisory)規(guī)則加了“推薦”標(biāo)示。

 


指針的安全規(guī)范

    《MISRAC2004》關(guān)于指針的規(guī)范主要分為三個(gè)部分:指針的類型轉(zhuǎn)換規(guī)則、指針運(yùn)算的規(guī)則和指針的有效性規(guī)則。


1.1
  指針的類型轉(zhuǎn)換

    指針類型轉(zhuǎn)換是個(gè)高風(fēng)險(xiǎn)的操作,所以應(yīng)該盡量避免進(jìn)行這個(gè)操作。MISRAC對其中可能造成嚴(yán)重錯(cuò)誤的情況作了嚴(yán)格的限定,選擇其中兩條作簡要分析。


    規(guī)則
11.4(推薦):指向不同數(shù)據(jù)類型的指針之間不能相互轉(zhuǎn)換。

思考如下程序:

uint8_t*pl

uint32)_t*p2;

p2=(uint32_t*)pl;

*注:uint8_t表示8位無符號整型,uint3_t表示32位無符號整型。*


    程序員希望將從
p1單元開始的4個(gè)字節(jié)組成一個(gè)32付的整型來參與運(yùn)算。


    如果
CPU允許各種數(shù)據(jù)對象存放在任意的存儲單元,則以上轉(zhuǎn)換沒有問題。但某些CPU對某種()數(shù)據(jù)類型加強(qiáng)了對齊限制,要求這些數(shù)據(jù)對象占用一定的地址空間,比如某些字節(jié)尋址的CPU會要求32(4字節(jié))整型存放在4的整倍數(shù)地址上。在這個(gè)前提下.思考程序中的指針轉(zhuǎn)換:假設(shè)pl一開始指向的是0x00O3單元(uint8_t型的整型沒有對齊要求),則執(zhí)行最后一行強(qiáng)制轉(zhuǎn)換后,p2到底指向哪個(gè)單元就無法預(yù)料了。


    規(guī)則
1 1.5:指針轉(zhuǎn)換過程中不允許丟失指針的constvolatile屬性。按如下定義指針:

uIntl6t    x;

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+


    以上非法指針類型轉(zhuǎn)換將會丟失
const或者volatile類型。丟失const屬性,將有可能導(dǎo)致在對只讀內(nèi)容進(jìn)行寫操作時(shí),編譯器不會發(fā)出警告,編譯器將不對具有volatile屬性的變量作優(yōu)化;丟失volatile屬性,編譯器的優(yōu)化可能導(dǎo)致程序員預(yù)先設(shè)計(jì)的硬件時(shí)序操作失效,這樣的錯(cuò)誤很難發(fā)現(xiàn)。關(guān)于constvolatile關(guān)鍵字的詳細(xì)作用,讀者可參考ISOC獲取更多信息。


1
指針的運(yùn)算

    ISOC標(biāo)準(zhǔn)中,對指向數(shù)組成員的指針運(yùn)算(包括算術(shù)運(yùn)算、比較等)做了規(guī)范定義,除此以外的指針運(yùn)算屬于未定義(undefined)范圍,具體實(shí)現(xiàn)有賴于具體編譯器,其安全性無法得到保障,MISRAC中對指針運(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)算帶來的隱患,尤其是程序動態(tài)運(yùn)行時(shí)可能發(fā)生的數(shù)組越界等問題,
MISRAC對指針運(yùn)算作了更為嚴(yán)格的規(guī)定。規(guī)則17 4:只允許用數(shù)組索引做指針運(yùn)算。按如下方式定義數(shù)組和指針:

uint8_t    a[10];

uint8_t    *p;


    則
*(p+5)=O是不允許的.而p[5]=O則是允許的,盡管就這段程序而言,二者等價(jià)。


    以下給出一段程序,讀者可參照相應(yīng)程序行的注釋,細(xì)細(xì)品味上述規(guī)則的含義。

void my_fn(uInt*_t*p1uint8_t p2[]){


     ①其實(shí)此處的算術(shù)運(yùn)算僅限定于指針加減某個(gè)整數(shù).比如
ppoint=point5ppoint++等。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;  *不允許,p1不是指向數(shù)組的指針*

    p3=&p1[5];*不允許,pl不是指向數(shù)組的指針*

    p2[0]=O;

    index++;

    index=index+5

    p2[index]=0    *允許*

    *(p2+index)=O;  *不允許*

    p4=&p2[5]    *允許*

    }


1
3
  指針的有效性

    下面介紹《MISRAC2004》中關(guān)于指針有效性的規(guī)則。


    規(guī)則
17 6:動態(tài)分配對象的地址不允許在本對象消亡后傳給另外一個(gè)對象。


    這條規(guī)則的實(shí)際意義是不允許將棧對象的地址傳給外部作用域的對象。

請看以下這段程序:

#includestdi0h

char*getm(void){

char p[]=hello world″;

return p

intmain(){

    char* str=NULL;

    str=getm();

    printf(str);


    程序員希望最后的輸出結(jié)果是″
hello world″這個(gè)字符串,然而實(shí)際運(yùn)行時(shí),卻出現(xiàn)亂碼(具體內(nèi)容依賴于編譯環(huán)境)。


   
簡單分析一下,由于chat p[]=hell0 world″這條語句是在棧中分配空間存儲″hell0 world″這個(gè)字符串,當(dāng)函數(shù)getm()返回的時(shí)候,已分配的空間將會被釋放(但內(nèi)容并不會被銷毀),而priM(str)涉及系統(tǒng)調(diào)用,有數(shù)據(jù)壓棧,會修改從前分配給數(shù)組p[]存儲空間的內(nèi)容,導(dǎo)致程序無法得到預(yù)期的效果。


    倘若將
getm()函數(shù)體中的char p[]=hell0 world″程序行改成char*q=hello world″,則執(zhí)行main( )的時(shí)候可以正確輸出″hello world″,這是由于q指向的是靜態(tài)數(shù)據(jù)區(qū),而非棧中的某個(gè)單元。


   
所以,數(shù)組名是指針不假,但在實(shí)現(xiàn)細(xì)節(jié)上還是有很大的差異,程序員在使用指針的時(shí)候必須慎之又慎。

 

2  結(jié)構(gòu)體、聯(lián)合體的安全規(guī)范

    規(guī)則18 4:不允許使用聯(lián)合體。這是一個(gè)不太近情理的規(guī)定,在具體闡述為何《MISRAC2004》如此“痛恨”聯(lián)合體之前,首先需要明確與聯(lián)合體相關(guān)的細(xì)節(jié):

    ①聯(lián)合體的末尾有多少個(gè)填充單元?

    ②聯(lián)合體中的各個(gè)成員如何對齊?

    ③多字節(jié)的數(shù)據(jù)類型高低字節(jié)如何排放順序?

    ④如果包含位字段(bitfield),各位如何排放順序?


   
針對細(xì)節(jié)3舉個(gè)例子。

程序段21

typedef union{

    uilat32_t word;

    uint8_t bytes[4];

}word_msg_t;

unit32_t read_nasg(void){

  word_rnsg_t tmp

*注:tmn bvte[O]對府干tmpword的高8位,tmp  byter[l]對應(yīng)于

tmp.WOfO的次高8位,依次類推。*

tmpbytes[O]=read_byte();

tmpbytes[1]=read_byte();

tmpbytes[2]=read_byte();

tmpbytes[3]=read_byte();

retlarn(trapword);

}

    以上代碼格式在各種通信協(xié)議中使用的頻率很高,接收端接收到的數(shù)據(jù)一般都以字節(jié)為單位存放,主控程序需要根據(jù)相應(yīng)的協(xié)議將接收到的多個(gè)字節(jié)進(jìn)行組合。為了實(shí)現(xiàn)相同的功能,《MISRA-C2004》推薦了read_msg()函數(shù)的另外一種寫法。

程序段22

uint32_trcad_msg(void){

uint32_t word;

Word=((unit32_t)read_byte())<<24

word=word(((unit32_t)read_byte())<<16);

word=word(((unit32_t)read_byted_byte<<8);

word=word(((unit32_t)read_byte());

return(word)

}


    無論從程序的清晰程度還是執(zhí)行效率來講,程序段
21都優(yōu)于程序段22。然而,程序段21Intel 80x86Pentlurn體系(1ittleendian,存儲多字節(jié)整數(shù)的時(shí)候低字節(jié)存放在低地址,高字節(jié)存放在高地址)CPU中和在Motorola 68K體系(bigendian,存儲多字節(jié)整數(shù)的時(shí)候高字節(jié)存放在低地址,低字節(jié)存放在高地址)cPu中的執(zhí)行結(jié)果完全不一樣。假設(shè)read_byte()函數(shù)返回的數(shù)據(jù)依次是0x01、0x02、0x030x04,則在Intel體系中,程序段21

read_msg()函數(shù)的返回值是0x432l;在Motorola體系中,read_msg()的返回值是0x1234。


    無論在
Intel體系還是Motorola體系中,程序段22read_msg()的返回值都是0x1 234


    以上是聯(lián)合體中多字節(jié)整型字節(jié)排放順序不定導(dǎo)致漏洞的一個(gè)例子。倘若不明確聯(lián)合體末尾填充的細(xì)節(jié),或者不清楚聯(lián)合體成員的對齊方式,或者不注意聯(lián)合體中位字段成員的位排列次序,都有可能導(dǎo)致錯(cuò)誤。作為將安全性放在第一位的
C標(biāo)準(zhǔn),MlSRAC禁止使用聯(lián)合體并非不可理喻。


   
然而,聯(lián)合體畢竟是C語言的一個(gè)重要元素,所以MISRAC主張禁止使用聯(lián)合體的同時(shí),也為效率和資源要求比較苛刻的情況開了一扇門,程序員在明確聯(lián)合體各個(gè)實(shí)現(xiàn)細(xì)節(jié)的前提下,在萬不得已的時(shí)候,仍可謹(jǐn)慎使用聯(lián)合體,在不同體系的CPU間移植程序的時(shí)候要注意做相應(yīng)的修改。


    此外,《
MISRAC2004》中也對結(jié)構(gòu)體和聯(lián)合體的編程風(fēng)格作了限定。


    規(guī)則
18 1:所有結(jié)構(gòu)體和聯(lián)合體的定義必須保證完整性。


    由于涉及
ISOC中類型定義完整性等概念,礙于篇幅的原因,此處就不再贅述,讀者可以參閱《MISRA-C2004》一書和ISOC標(biāo)準(zhǔn)以了解更多信息,完善自己的編程風(fēng)格。

 

3  小  結(jié)

    總而言之,對于C程序中最為靈活的指針、結(jié)構(gòu)體和聯(lián)合體,程序員不僅僅要關(guān)注其定義和操作的一般方法,更要注重實(shí)現(xiàn)的細(xì)節(jié)。由于指針、聯(lián)合體等的功能性錯(cuò)誤一般都可以逃過編譯器的檢查,所以稍有疏忽,就可能導(dǎo)致程序在運(yùn)行的時(shí)候出現(xiàn)嚴(yán)重錯(cuò)誤,程序員必須以嚴(yán)謹(jǐn)甚至苛刻的態(tài)度對待指針、結(jié)構(gòu)體和聯(lián)合體。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護(hù)是驅(qū)動電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機(jī)驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計(jì)工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉