案例分析1
void GetMemory(char *p)
{
p = (char *)malloc(100);
}
void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}
程序不能运行。str一直是NULL指针,strcpy操作需要目标数组的大小不小于源数组大小,所以会造成程序崩溃。程序崩溃的原因在于GetMemory不能动态传递内存,Test调用GetMemory时使用的是值传递,即调用后p==null,str==null,p和str没有关联关系,因此用p申请内存后,不能将该内存传递给str。而且,由于形参在函数调用结束后会自动消亡,p申请的内存无法引用,造成了内存泄漏。
案例分析2
void GetMemory2(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory2(&str, 100);
strcpy(str, "hello");
printf(str);
}
程序可以运行,即能输出“hello”。与案例1不同的是,Test在调用GetMemory2时传递的是str的地址,即char指针的地址。GetMemory2的第一个形参p是指向char指针(char *)的指针。这样,*p指向的是str的地址,*p = (char *)malloc(num)相当于用str的地址动态的申请一块内存。GetMemory2返回后,str依然指向该内存,所以可以调用strcpy函数。
案例分析3
void GetMemory(char *&p)
{
p = (char *)malloc(100);
}
void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str, "hello");
printf(str);
}
程序可以正常运行。Test()调用GetMemory时将str传递给p,注意,这是p是个指向char指针的引用,实参和形参结合的过程中,将&p绑定到str上,即相当于p是str的一个别名。
案例分析4
char *GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(str);
}
程序发生乱码。在GetMemory中,p[]=”hello world”属于局部变量,局部变量在函数返回后自动消亡,这样GerMemory返回后,str指向的地址不是NULL,但内容未知。
案例分析5
void Test(void)
{
char *str = (char *) malloc(100);
strcpy(str,"hello");
free(str);
if(str != NULL)//释放内存后,str并不为空,即传说中的野指针,if判断为真。
{
strcpy(str,"world");//此时对str进行赋值,
printf(str);
}
}
“野指针”不是NULL指针,是指向“垃圾”内存(不可用内存)的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if无法判断一个指针是正常指针还是“野指针”。有个良好的编程习惯是避免“野指针”的唯一方法。
野指针的成因主要有三种:
一、指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。
二、指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。
三、指针操作超越了变量的作用范围.