1. 程式人生 > 實用技巧 >通過一個記憶體洩露例子體會引數傳遞

通過一個記憶體洩露例子體會引數傳遞

程式例子如下:

1 #include <stdio.h>

2 #include <stdlib.h>

3

4 void func(int *p , int n)

5 {

6 printf("line 6 %p\n",p);

7 p = malloc(n);

8 printf("line 8 %p\n",p);

9 if (p == NULL)

10 exit(1);

11 return ;

12 }

13

14 int main ()

15 {

16 int size = 100;

17 int *p=NULL;

18 printf("lin 18 %p\n",p);

19 func(p,size);

20 printf("line 20 %p\n",p);

21

22 free(p);

23

24 exit(0);

25 }

程式的執行過程中,不會報任何錯誤,就是動態申請空間和釋放空間的過程。15行定義了一個指標型別的變數。16,呼叫了自定義的func函式,並且傳遞引數p和size。問題就是出在引數傳遞上。

wKiom1aniTzBIMqhAACFbZSO-EQ963.png

p是一個地址,但是main 函式呼叫func(p,size)的時候實際進行的傳值呼叫。所以,在main中釋放p會導致在func子函式中申請的空間無人釋放的問題。

解決辦法:

一、採用二級指標的方式。使得main中的p 和 func子函式的中的是同一個地址。

程式碼如下:

1 #include <stdio.h>

2 #include <stdlib.h>

3

4 void func(int **p , int n)

5 {

6 printf("line 6 %p\n",p);

7 *p = malloc(n);

8 printf("line 8 %p\n",p);

9 if (p == NULL)

10 exit(1);

11 return ;

12 }

13

14 int main ()

15 {

16 int size = 100;

17 int *p=NULL;

18 printf("lin 18 %p\n",p);

19 func(&p,size);

20 printf("line 20 %p\n",p);

21

22 free(p);

23

24 exit(0);

25 }


wKioL1ani7TQaXd4AABOr4B9mIw737.png

需要深入理解,到底什麼時候二級指標,在本例子中,二級指標可以實現傳遞的p本身而不是副本到func函式中。func函式申請到的100位元組的動態記憶體空間的起始地址就是儲存在func和main中的p這個指標變數中。此時在main中free不會導致記憶體洩露。

方法二:返回指標的方式:

1 #include <stdio.h>

2 #include <stdlib.h>

3

4 void * func(int *p , int n)

5 {

6 printf("line 6 %p\n",p);

7 p = malloc(n);

8 printf("line 8 %p\n",p);

9 if (p == NULL)

10 exit(1);

11 return p ;

12 }

13

14 int main ()

15 {

16 int size = 100;

17 int *p=NULL;

18 printf("lin 18 %p\n",p);

19 p = func(p,size);

20 printf("line 20 %p\n",p);

21

22 free(p);

23

24 exit(0);

25 }

通過返回地址得方式,讓main中p指向100位元組的動態記憶體空間,在main結束的時候,free這100個位元組的記憶體空間,顯然不會導致記憶體洩露。

總結:本例子,想從引數傳遞的角度,探討傳值和傳址的不同。對普通變數而言,傳址就是傳遞變數的地址。但是對指標變數要想傳遞地址,就需要使用二級指標。指標是地址不錯,但是存放指標的記憶體單元也需要有地址。就是傳遞儲存該記憶體單元地址【也就是二級指標】,就可以實現在主調和被調函式之間使用同一指標操作。


轉載於:https://blog.51cto.com/hongyilinux/1738823