堆棧
棧中分配局部變量空間,是系統自動分配空間。定義一個 char a;系統會自動在棧上爲其開闢空間。因爲棧上的空間是自動分配自動回收的,因此棧上的數據的生存週期只是在函數的運行過程當中,運行後就釋放掉,不能夠再訪問。java
堆區分配程序員申請的內存空間,堆上的數據只要程序員不釋放空間,就一直能夠訪問到,不過缺點是一旦忘記釋放會形成內存泄露。
程序員
靜態區是分配靜態變量,全局變量空間的。c#
- int a = 0; 全局初始化區
- char *p1; 全局未初始化區
- main(){
- int b;
- char s[] = "abc";
- char *p2;
- char *p3 = "123456";
- static int c =0;
- p1 = (char *)malloc(10);
GetMemory1
- void GetMemory1(char *p)
- {
- p = (char *)malloc(100);
- }
-
- void Test1(void)
- {
- char *str = NULL;
- GetMemory1(str);
- strcpy(str, "hello world");
- printf(str);
- }
結果:
分析:數組
毛病出在函數GetMemory1 中。編譯器老是要爲函數的每一個參數製做臨時副本,指針參數p的副本是 _p,編譯器使 _p = p。若是函數體內的程序修改了_p的內容,就致使參數p的內容做相應的修改。這就是指針能夠用做輸出參數的緣由。在本例中,_p申請了新的內存,只是把 _p所指的內存地址改變了,可是p絲毫未變。因此函數GetMemory並不能輸出任何東西。事實上,每執行一次GetMemory1就會泄露一塊內存,由於沒有用free釋放內存。Test1中調用GetMemory1時,函數參數爲str的副本不是str自己。ide
GetMemory2
- void GetMemory2(char **p, int num)
- {
- *p = (char *)malloc(num);
- }
-
- void Test2(void)
- {
- char *str = NULL;
- GetMemory2(&str, 100);
- strcpy(str, "hello");
- printf(str);
- }
結果:輸出hello
分析:動態分配的內存不會自動釋放;函數
沒有測試是否成功分配了內存,應該有if (*p == NULL) { ……} 之類的語句處理內存分配失敗的其狀況。測試
GetMemory3
- char * GetMemory3(void)
- {
- char p[] = "hello world";
- return p;
- }
- void Test3(void)
- {
- char *str = NULL;
- str = GetMemory3();
- printf(str);
- }
結果:輸出亂碼。
分析:字符數組p存在於棧空間,是局部變量,函數返回後,內存空間被釋放,所以輸出無效值。字符數組的值是能夠修改的,例如p[0] = 't‘。
spa
GetMemory4
- char *GetMemory4(void)
- {
- char *p = "hello";
- return p;
- }
-
- void Test4(void)
- {
- char *str = NULL;
- str = GetMemory4();
- cout<< str << endl;
- }
結果:輸出hello
分析:p指向的是字符串常量,字符串常量保存在只讀的數據段,是全局區域,但不是像全局變量那樣保存在普通數據段(靜態存儲區)。沒法對p所指的內存的內容修改,例如p[0] = 'y;這樣的修改是錯誤的。
GetMemory5
- char *GetMemory5(void)
- {
- return "hello";
- }
- void Test3(void)
- {
- char *str = NULL;
- str = GetMemory5();
- printf(str);
- }
結果:輸出hello
分析:直接返回常量區。
GetMemory6
- void GetMemory6(void) {
- char *str = (char*)malloc(100);
- strcpy(str, "hello");
- free(str);
-
- if (str != NULL) {
- strcpy(str, "world");
- printf(str);
- }
- }
-
- void main(){
- GetMemory6();
- }
結果:可以輸出world,但程序存在問題。
分析:程序出現了野指針。.net
野指針只會出如今像C和C++這種沒有自動內存垃圾回收功能的高級語言中, 因此java或c#確定不會有野指針的概念. 當咱們用malloc爲一個指針分配一個空間後, 用完這個指針,把它free掉,可是沒有讓這個指針指向NULL或某一個特定的空間。如上面程序同樣,將str進行free後,只是釋放了指針所指的內存,但指針並無釋放掉,此時指針所指的是垃圾內存;這樣的話,if語句永爲真,if判斷無效。delete也存在一樣的問題。
指針
防止產生野指針:(1)指針變量必定要初始化爲NULL,由於任何指針變量剛被建立時不會自動成爲NULL指針,它的缺省值是隨機的。(2)當free或delete後,將指針指向NULL。一般判斷一個指針是否合法,都是使用if語句測試該指針是否爲NULL。
原文:http://blog.csdn.net/u013074465/article/details/42784267