程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> c說話內存洩漏示例解析

c說話內存洩漏示例解析

編輯:關於C++

c說話內存洩漏示例解析。本站提示廣大學習愛好者:(c說話內存洩漏示例解析)文章只能為提供參考,不一定能成為您想要的結果。以下是c說話內存洩漏示例解析正文


准確的內存治理的主要性
存在內存毛病的 C 和 C++ 法式會招致各類成績。假如它們洩露內存,則運轉速度會逐步變慢,並終究停滯運轉;假如籠罩內存,則會變得異常軟弱,很輕易遭到歹意用戶的進擊。從 1988 年有名的莫裡斯蠕蟲 進擊到有關 Flash Player 和其他症結的批發級法式的最新平安警報都與緩沖區溢出有關:“年夜多半盤算機平安破綻都是緩沖區溢出”,Rodney Bates 在 2004 年寫道。

在可使用 C 或 C++ 的處所,也普遍支撐應用其他很多通用說話(如 Java™、Ruby、Haskell、C#、Perl、Smalltalk 等),每種說話都有浩瀚的喜好者和各自的長處。然則,從盤算角度來看,每種編程說話優於 C 或 C++ 的重要長處都與便於內存治理親密相干。與內存相干的編程是如斯主要,而在理論中准確運用又是如斯艱苦,乃至於它安排著面向對象編程說話、功效性編程說話、高等編程說話、聲明性編程說話和別的一些編程說話的一切其他變量或實際。

與多數其他類型的罕見毛病一樣,內存毛病照樣一種隱性傷害:它們很難再現,症狀平日不克不及在響應的源代碼中找到。例如,不管什麼時候何地產生內存洩露,都能夠表示為運用法式完整沒法接收,同時內存洩露不是不言而喻。

是以,出於一切這些緣由,須要特殊存眷 C 和 C++ 編程的內存成績。讓我們看一看若何處理這些成績,先不談是哪一種說話。

內存毛病的種別
起首,不要掉去信念。有許多方法可以對於內存成績。我們先列出一切能夠存在的現實成績:

•內存洩露
•毛病分派,包含年夜量增長 free() 釋放的內存和未初始化的援用
•懸空指針
•數組界限背規

這是一切類型。即便遷徙到 C++ 面向對象的說話,這些類型也不會有顯著變更;不管數據是簡略類型照樣 C 說話的 struct 或 C++ 的類,C 和 C++ 中內存治理和援用的模子在道理上都是雷同的。以下內容絕年夜部門是“純 C”說話,關於擴大到 C++ 重要留作演習應用。

內存洩露
在分派資本時會產生內存洩露,然則它從不收受接管。上面是一個能夠失足的模子(請拜見清單 1):

清單 1. 簡略的潛伏堆內存喪失懈弛沖區籠罩

void f1(char *explanation) { char *p1; p1 = malloc(100); sprintf(p1,"The f1 error occurred because of '%s'.", explanation); local_log(p1); }

您看到成績了嗎?除非 local_log() 對 free() 釋放內存具有不平常的呼應才能,不然每次對 f1 的挪用都邑洩露 100 字節。在記憶棒增量分發數兆字節內存時,一次洩露是眇乎小哉的,然則持續操作數小時後,即便如斯小的洩露也會減弱運用法式。

在現實的 C 和 C++ 編程中,這缺乏以影響您對 malloc() 或 new 的應用,本部門開首的句子提到了“資本”不是僅指“內存”,由於還有相似以下內容的示例(請拜見清單 2)。FILE 句柄能夠與內存塊分歧,然則必需對它們賜與一致存眷:

清單 2. 來自資本毛病治理的潛伏堆內存喪失

int getkey(char *filename) { FILE *fp; int key; fp = fopen(filename, "r"); fscanf(fp, "%d", &key); return key; }

fopen 的語義須要彌補性的 fclose。在沒有 fclose() 的情形下,C 尺度不克不及指定產生的情形時,極可能是內存洩露。其他資本(如旌旗燈號量、收集句柄、數據庫銜接等)異樣值得斟酌。

內存毛病分派
毛病分派的治理不是很艱苦。上面是一個毛病分派示例(請拜見清單 3):

清單 3. 未初始化的指針

void f2(int datum) { int *p2; /* Uh-oh! No one has initialized p2. */ *p2 = datum; ... }

關於此類毛病的好新聞是,它們普通具有明顯成果。在 AIX® 下,對未初始化指針的分派平日會立刻招致segmentation fault 毛病。它的利益是任何此類毛病都邑被疾速地檢測到;與消費數月時光能力肯定且難以再現的毛病比擬,檢測此類毛病的價值要小很多。

在此毛病類型中存在多個變種。free() 釋放的內存比 malloc() 更頻仍(請拜見清單 4):

清單 4. 兩個毛病的內存釋放

/* Allocate once, free twice. */ void f3() { char *p, *pp; p = malloc(10);
pp=p;
free(p); ... free(pp); } /* Allocate zero times, free once. */ void f4() { char *p;
...
/* Note that p remains uninitialized here. */ free(p); }

這些毛病平日也不太嚴重。雖然 C 尺度在這些情況中沒有界說詳細行動,但典范的完成將疏忽毛病,或許疾速而明白地對它們停止標志;總之,這些都是平安情況。

懸空指針
懸空指針比擬辣手。當法式員在內存資本釋放後應用資本時會產生懸空指針(請拜見清單 5):

清單 5. 懸空指針

void f8() { struct x *xp; xp = (struct x *) malloc(sizeof (struct x)); xp.q = 13; ... free(xp); ... /* Problem! There's no guarantee that the memory block to which xp points hasn't been overwritten. */ return xp.q; }

傳統的“調試”難以隔離懸空指針。因為上面兩個顯著緣由,它們很難再現:

•即便影響提早釋放內存規模的代碼已當地化,內存的應用依然能夠取決於運用法式乃至(在極端情形下)分歧過程中的其他履行地位。

•懸空指針能夠產生在以奧妙方法應用內存的代碼中。成果是,即便內存在釋放後立刻被籠罩,而且新指向的值分歧於預期值,也很難辨認出新值是毛病值。

懸空指針赓續威逼著 C 或 C++ 法式的運轉狀況。

數組界限背規
數組界限背規非常風險,它是內存毛病治理的最初一個重要種別。回頭看一下清單 1;假如 explanation 的長度跨越 80,則會產生甚麼情形?答復:難以預感,然則它能夠與優越情況相差甚遠。特殊是,C 復制一個字符串,該字符串不適於為它分派的 100 個字符。在任何慣例完成中,“跨越的”字符會籠罩內存中的其他數據。內存中數據分派的結構異常龐雜而且難以再現,所以任何症狀都弗成能追溯到源代碼級其余詳細毛病。這些毛病平日會招致數百萬美元的喪失。

.辣手的內存洩露

static char *important_pointer = NULL; void f9() { if (!important_pointer) important_pointer = malloc(IMPORTANT_SIZE); ... if (condition) /* Ooops! We just lost the reference important_pointer already held. */ important_pointer = malloc(DIFFERENT_SIZE); ... }
do not前往部分指針變量或許部分變量的指針,除非是一個static部分變量
char *f0() {     char temp[]="123456789"; //加上static 才是准確的
return temp; }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved