国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

查看: 3843|回復: 4
打印 上一主題 下一主題

C語言之內存使用

[復制鏈接]
跳轉到指定樓層
樓主
發表于 2014-4-27 02:35:33 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
關鍵詞: C語言
這里我和大家一起探討c語言的內存使用。
  曾經有同行寫了一個把整數轉換為字符串的函數:
char *itoa (int n)
{
  char retbuf[20];
  sprintf(retbuf, "%d", n);
  return retbuf;
}
  倘若我調用該函數:char *str5 = itoa(5),str5會是什么數值?
  結果是不確定,唯一能確定的是結果不會是我們想要的 “5”。
    為何呢?因為retbuf定義在函數體中,它是局部變量,局部變量的內存空間位于堆棧(stack)中,同時其作用范圍也僅限于所在的函數中。此時當itoa()函數返回時,retbuf在堆棧中的內容將被回收,這塊內存地址將可能被存放別的內容。所以把局部變量返回給函數調用者是欠妥的,也是不應該的做法。
  這樣我們該如何解決問題呢,別擔心,方法有很多且不止一個,下面就來闡述三種能解決這個問題的方法:
  1)、在itoa()函數內部用malloc() 為指針分配內存,同時將結果存放到里面,最后將retbuf返回給調用者。因為此時retbuf分配于堆(heap)中,其對應空間不會隨著函數返回而釋放,所以能達到我們的目的。
  不過這里需要注意:調用者在不需要retbuf的時候必須人工把它釋放,調用free函數來回收空間,否則就造成內存泄漏了。倘若該函數和調用函數的都是同一個人所寫則問題不大,否則將比較容易會疏漏此釋放內存的動作。
  2)、在itoa()函數內部定義靜態變量static char retbuf[20],這同樣能保證函數返回后retbuf的空間不被回收,這是因為靜態變量并不是存放在堆棧中,而是存放在一個叫“.bss”段的地方,該地方的內容是不會因函數返回而被回收的。
  這種辦法雖然能解決問題,不過它也導致了函數變成了一個不可重入函數(即不能保證相同的輸入肯定有相同的輸出)。同時, retbuf [] 中的內容會被函數的下一次調用結果所代替,該辦法不值得推薦。
  3)、使用指針參數,將函數定義為char *itoa(int n, char *retbuf),并且retbuf由函數調用者申請和釋放,這時候itoa()只是將轉換結果存放到retbuf。
  很明顯這種方法比第一、二種方法強,首先避免了方法1對函數的影響,同時也規避了方法2對內存分配釋放的影響,是業內一種比較通用流行的做法。
  擴展分析:
  如果就該問題本身而言,想必大家都可以迅速想到答案,問題關鍵就在對memory這類敏感資源的正確和合理地利用,下來我們對內存做個簡單的分析:


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


問題:內存分配 & sizeof
  如果使用sizeof來計算一個指針變量,希望得到這個指針變量所分配的內存塊的大小,可以嗎?


char *p = NULL;
int nMemSize = 0;

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


  答案與分析:


  結果是達不到你的要求的,sizeof只能告訴你指針變量本身占用的內存大小。指針所指向的內存,如果是malloc分配的,sizeof 是無法知道的。換言之,malloc分配的內存是無法向內存管理模塊進行事后查詢的,當然你是可以自己編寫代碼來管理維護。


  問題:棧內存使用


  下面的程序運行會有什么問題?


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


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


  答案與分析:


  返回棧內存,內存可能被銷毀也可能不被及時銷毀,但可以肯定的是出了作用域之后已被標記成可被系統使用,因此會返回亂七八糟不可知內容。當然,返回的指針的內容,應該是不變的,特殊時候是有用的,比如,可以用來探測系統內存分配規律等。


  問題:內存使用相關編程規范


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


  答案與分析:


  除非做一件從沒有人做過的事情,不然都是有捷徑可言的,答案那就是站在前人的肩膀上,當今各個大公司都有自己的編碼規范,這些規范凝聚了許多的經驗教訓,有較高的使用價值,考慮到這些規范在網上流傳很多,這里我就不再列舉了,感興趣的,推薦參考林銳的《高質量C/C++編程指南》。


沙發
發表于 2014-4-28 17:45:04 | 只看該作者
是想闡述函數調用過程么?
板凳
 樓主| 發表于 2014-4-30 02:39:26 | 只看該作者
云峰 發表于 2014-4-28 17:45
是想闡述函數調用過程么?

不是,這里是將內存的使用,比如堆棧和堆的區別。
地板
發表于 2014-5-4 09:00:59 | 只看該作者
復制下來!。。。。。。!我自己好好學習!。。。。。。。。。。。!

謝謝.jpg (8.65 KB)

謝謝.jpg
地下室
發表于 2014-5-4 20:46:30 | 只看該作者
Hugo801122 發表于 2014-4-30 02:39
不是,這里是將內存的使用,比如堆棧和堆的區別。

但函數的調用過程不就是堆棧的使用過程么
您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表
主站蜘蛛池模板: 婷婷在线播放 | 伊人导航| 欧美97色伦影院在线观看 | 免费一级a毛片夜夜看 | 欧美日韩免费播放一区二区 | 花季传媒v3084下载入口 | 婷婷日韩| 精品视自拍视频在线观看 | 91国内揄拍国内精品对白 | 天天综合天天色 | 亚洲香蕉网久久综合影院3p | 国产成人aaa在线视频免费观看 | 免费观看黄a一级视频日本 免费观看黄a一级视频 | 在线观看麻豆精品国产不卡 | 欧美高清在线精品一区二区不卡 | 91av视频在线免费观看 | 国产高清黄色 | 久久精品亚洲一区二区三区浴池 | 成人免费视频在线 | 九九视频热| 在线看片黄 | 国产69精品久久久久妇女 | 精品国产区一区二区三区在线观看 | 欧美卡1卡2卡三卡网站入口 | 成人一级视频 | 爽好舒服宝贝添奶吻戏 | 精品一区二区在线欧美日韩 | 97视频在线观看免费播放 | 欧美日韩精品高清一区二区 | 国产成人欧美视频在线 | 亚洲va久久久久 | 重口调教女虐女长篇小说 | 奶茶视频有容乃大 | 羞羞视频在线观看网站 | 欧美成人免费在线视频 | 亚洲综合视频在线观看 | 中文字幕日韩一区二区三区不卡 | 和阿同居的日子hd | 日韩在线视频免费观看 | 97精品在线 | 99热在线精品播放 |