色偷偷偷久久伊人大杳蕉,色爽交视频免费观看,欧美扒开腿做爽爽爽a片,欧美孕交alscan巨交xxx,日日碰狠狠躁久久躁蜜桃

電子工程網(wǎng)

標(biāo)題: C語(yǔ)言之內(nèi)存使用 [打印本頁(yè)]

作者: Hugo801122    時(shí)間: 2014-4-27 02:35
標(biāo)題: C語(yǔ)言之內(nèi)存使用
這里我和大家一起探討c語(yǔ)言的內(nèi)存使用。
  曾經(jīng)有同行寫了一個(gè)把整數(shù)轉(zhuǎn)換為字符串的函數(shù):
char *itoa (int n)
{
  char retbuf[20];
  sprintf(retbuf, "%d", n);
  return retbuf;
}
  倘若我調(diào)用該函數(shù):char *str5 = itoa(5),str5會(huì)是什么數(shù)值?
  結(jié)果是不確定,唯一能確定的是結(jié)果不會(huì)是我們想要的 “5”。
    為何呢?因?yàn)閞etbuf定義在函數(shù)體中,它是局部變量,局部變量的內(nèi)存空間位于堆棧(stack)中,同時(shí)其作用范圍也僅限于所在的函數(shù)中。此時(shí)當(dāng)itoa()函數(shù)返回時(shí),retbuf在堆棧中的內(nèi)容將被回收,這塊內(nèi)存地址將可能被存放別的內(nèi)容。所以把局部變量返回給函數(shù)調(diào)用者是欠妥的,也是不應(yīng)該的做法。
  這樣我們?cè)撊绾谓鉀Q問(wèn)題呢,別擔(dān)心,方法有很多且不止一個(gè),下面就來(lái)闡述三種能解決這個(gè)問(wèn)題的方法:
  1)、在itoa()函數(shù)內(nèi)部用malloc() 為指針?lè)峙鋬?nèi)存,同時(shí)將結(jié)果存放到里面,最后將retbuf返回給調(diào)用者。因?yàn)榇藭r(shí)retbuf分配于堆(heap)中,其對(duì)應(yīng)空間不會(huì)隨著函數(shù)返回而釋放,所以能達(dá)到我們的目的。
  不過(guò)這里需要注意:調(diào)用者在不需要retbuf的時(shí)候必須人工把它釋放,調(diào)用free函數(shù)來(lái)回收空間,否則就造成內(nèi)存泄漏了。倘若該函數(shù)和調(diào)用函數(shù)的都是同一個(gè)人所寫則問(wèn)題不大,否則將比較容易會(huì)疏漏此釋放內(nèi)存的動(dòng)作。
  2)、在itoa()函數(shù)內(nèi)部定義靜態(tài)變量static char retbuf[20],這同樣能保證函數(shù)返回后retbuf的空間不被回收,這是因?yàn)殪o態(tài)變量并不是存放在堆棧中,而是存放在一個(gè)叫“.bss”段的地方,該地方的內(nèi)容是不會(huì)因函數(shù)返回而被回收的。
  這種辦法雖然能解決問(wèn)題,不過(guò)它也導(dǎo)致了函數(shù)變成了一個(gè)不可重入函數(shù)(即不能保證相同的輸入肯定有相同的輸出)。同時(shí), retbuf [] 中的內(nèi)容會(huì)被函數(shù)的下一次調(diào)用結(jié)果所代替,該辦法不值得推薦。
  3)、使用指針參數(shù),將函數(shù)定義為char *itoa(int n, char *retbuf),并且retbuf由函數(shù)調(diào)用者申請(qǐng)和釋放,這時(shí)候itoa()只是將轉(zhuǎn)換結(jié)果存放到retbuf。
  很明顯這種方法比第一、二種方法強(qiáng),首先避免了方法1對(duì)函數(shù)的影響,同時(shí)也規(guī)避了方法2對(duì)內(nèi)存分配釋放的影響,是業(yè)內(nèi)一種比較通用流行的做法。
  擴(kuò)展分析:
  如果就該問(wèn)題本身而言,想必大家都可以迅速想到答案,問(wèn)題關(guān)鍵就在對(duì)memory這類敏感資源的正確和合理地利用,下來(lái)我們對(duì)內(nèi)存做個(gè)簡(jiǎn)單的分析:


  1)、程序中分為不同的內(nèi)存段,包含:
  .heap - 堆,由程序顯式分配和收回,如果不收回就是內(nèi)存泄漏。
  .bss - 未初始化全局/靜態(tài)變量,在整個(gè)軟件執(zhí)行過(guò)程中有效;
  .data - 已初始化全局/靜態(tài)變量,在整個(gè)軟件執(zhí)行過(guò)程中有效;
  .stack - 函數(shù)調(diào)用棧,其中的內(nèi)容在函數(shù)執(zhí)行期間有效,并由編譯器負(fù)責(zé)分配和收回;
  2)、自己管理的內(nèi)存盡量自己申請(qǐng)和釋放。
  這其實(shí)是一個(gè)內(nèi)存分配和釋放的基本原則,比方說(shuō)上面的第二種方法,由itoa()分配的內(nèi)存,卻由調(diào)用者釋放,就不是一個(gè)十分好的做法,它明顯不如第三種,由調(diào)用者自己申請(qǐng)和釋放。此外該原則還有另一層意思:若使用一個(gè)指針,最好先確保它已經(jīng)指向一個(gè)合法地址,否則就自己分配,不然即非法地址訪問(wèn)。許多程序的致命錯(cuò)誤都是訪問(wèn)一個(gè)沒(méi)有指向合法內(nèi)存區(qū)的指針,也就是野指針,也包括空指針。


問(wèn)題:內(nèi)存分配 & sizeof
  如果使用sizeof來(lái)計(jì)算一個(gè)指針變量,希望得到這個(gè)指針變量所分配的內(nèi)存塊的大小,可以嗎?


char *p = NULL;
int nMemSize = 0;

p = malloc(1024);
nMemSize = sizeof(p);


  答案與分析:


  結(jié)果是達(dá)不到你的要求的,sizeof只能告訴你指針變量本身占用的內(nèi)存大小。指針?biāo)赶虻膬?nèi)存,如果是malloc分配的,sizeof 是無(wú)法知道的。換言之,malloc分配的內(nèi)存是無(wú)法向內(nèi)存管理模塊進(jìn)行事后查詢的,當(dāng)然你是可以自己編寫代碼來(lái)管理維護(hù)。


  問(wèn)題:棧內(nèi)存使用


  下面的程序運(yùn)行會(huì)有什么問(wèn)題?


char *GetString(void)
{
  char p[] = "hello world";
  return p;// 編譯器將提出警告
}


void Test4(void)
{
  char *str = NULL;
  str = GetString();// str 的內(nèi)容是垃圾
  cout<< str << endl;
}


  答案與分析:


  返回棧內(nèi)存,內(nèi)存可能被銷毀也可能不被及時(shí)銷毀,但可以肯定的是出了作用域之后已被標(biāo)記成可被系統(tǒng)使用,因此會(huì)返回亂七八糟不可知內(nèi)容。當(dāng)然,返回的指針的內(nèi)容,應(yīng)該是不變的,特殊時(shí)候是有用的,比如,可以用來(lái)探測(cè)系統(tǒng)內(nèi)存分配規(guī)律等。


  問(wèn)題:內(nèi)存使用相關(guān)編程規(guī)范


  如果想盡可能地避免內(nèi)存使用上的問(wèn)題,有什么捷徑嗎?


  答案與分析:


  除非做一件從沒(méi)有人做過(guò)的事情,不然都是有捷徑可言的,答案那就是站在前人的肩膀上,當(dāng)今各個(gè)大公司都有自己的編碼規(guī)范,這些規(guī)范凝聚了許多的經(jīng)驗(yàn)教訓(xùn),有較高的使用價(jià)值,考慮到這些規(guī)范在網(wǎng)上流傳很多,這里我就不再列舉了,感興趣的,推薦參考林銳的《高質(zhì)量C/C++編程指南》。



作者: 云峰    時(shí)間: 2014-4-28 17:45
是想闡述函數(shù)調(diào)用過(guò)程么?
作者: Hugo801122    時(shí)間: 2014-4-30 02:39
云峰 發(fā)表于 2014-4-28 17:45
是想闡述函數(shù)調(diào)用過(guò)程么?

不是,這里是將內(nèi)存的使用,比如堆棧和堆的區(qū)別。

作者: spy007868    時(shí)間: 2014-5-4 09:00
復(fù)制下來(lái)!。。。。。。!我自己好好學(xué)習(xí)!。。。。。。。。。。。。

謝謝.jpg (8.65 KB)

謝謝.jpg

作者: 云峰    時(shí)間: 2014-5-4 20:46
Hugo801122 發(fā)表于 2014-4-30 02:39
不是,這里是將內(nèi)存的使用,比如堆棧和堆的區(qū)別。

但函數(shù)的調(diào)用過(guò)程不就是堆棧的使用過(guò)程么




歡迎光臨 電子工程網(wǎng) (http://m.54549.cn/) Powered by Discuz! X3.4