在阅读《C语言深度解剖》一书,读到“无法把指针变量本身传递给一个函数”一节时,看到如下例子:
#include <malloc.h>
#include <string.h>
void GetMemory(char * p, int num)
{
p = (char *)malloc(num*sizeof(char));
}
int main()
{
char *str = NULL;
GetMemory(str,10);
strcpy(str,”hello”);
free(str);//free 并没有起作用,内存泄漏
return 0;
}
觉得很奇怪,在函数调用时,实参str将其值传递给形参p,而p和str都是指针,它们的值会同步更改,在子函数中分配完内存之后,str应该分配到了一段内存,怎么会发生内存泄漏呢?
带着疑问,调试书后紧接的两个例子,并观察str和p的地址值。发现,原来在前面的例子中,str传递的只是自身的值,不是str的地址,p和str是两个指向相同地址(0x00000000)的不同指针(两者自身的地址不相同):当p指向新分配的内存首地址(0x00384e18)时,str仍然指向0x00000000,str没有真正分配到内存,因此发生内存泄漏。而下面的两个例子中:第一个例子是通过函数值返回修改str,使得str指向新开辟内存的首地址来实现内存分配的;第二个例子是通过将str的自身地址传递给形参,使得*p和str为相同指针(两个变量的地址相同),在*p分配到内存的同时,str也分配到了内存。
书中的两个例子如下:
#include <malloc.h>
#include <string.h>
char * GetMemory(char * p, int num) //此时, p=0x00000000, &p=0x0012ff28, *p值无法访问,&p!=&str,
//可见p与str为两个不同的指针,但同时指向地址0x00000000
{
p = (char *)malloc(num*sizeof(char)); //调用内存分配函数,分配完一段内存之后,p指向这段内存
//的首地址,此时,p=0x00384e18, &p=0x0012ff28,
//*p=-51 '?(随机数)
return p;
}
void main()
{
char *str = NULL; //此时, &str=0x0012ff7c, str=0x00000000,*str值无法访问
str = GetMemory(str,10); //将p的内容赋给str,使str指向分配的那段内存的首地址
strcpy(str,"hello");
free(str);
}
//=============================================================================================//
#include <malloc.h>
#include <string.h>
void GetMemory(char **p, int num) //此时,p=0x0012ff7c, *p=0x00000000, **p值无法访
//问,&p=0x12ff28,p=&(*p)=&str,可见*p与str为两个相同的指
//针,修改其中任意一个的值都会改变另一个的值
{
*p = (char *)malloc(num*sizeof(char)); //调用内存分配函数,分配完一段内存之后,*p指向这段内
//存的首地址,与此同时,str也指向这段内存的首地址,此
//时,&p=0x0012ff28,p=0x0012ff7c, *p=0x00384e18
}
void main()
{
char *str = NULL; //此时, &str=0x0012ff7c, str=0x00000000,*str值无法访问
GetMemory(&str,10); //此时,str与*p同时指向新分配的内存的首地址,即0x00384e18
strcpy(str,"hello");
free(str);
}