程序例子如下:
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。问题就是出在参数传递上。
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 }
需要深入理解,到底什么时候二级指针,在本例子中,二级指针可以实现传递的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