正在悠闲地加载

指针参数在内存中的传递

代码一

View Code
void GetMemory(char *p , int num)
{ 
    p = (char *)malloc(sizeof(char) *num);
}

int main()
{ 
    char *str = NULL;
    GetMemory(str,100); //str 还是 NULL
    strcpy(str,"hello"); //运行出错
}

分析:编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是 _p,编译器使 _p = p。如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因。在本例中,_p申请了新的内存,只是把_p所指的内存地址改变了,但是p丝毫未变。所以函数GetMemory并不能输出任何东西。事实上,每执行一次GetMemory就会泄露一块内存,因为没有用free释放内存。
  如果非得要用指针参数去申请内存,那么应该改用“指向指针的指针”。

代码二

View Code
void GetMemory(char **p, int num)
{
    *p = (char *)malloc(sizeof(char) * num);
}

int main()
{
    char *str = NULL;
    GetMemory(&str,100); //看清传入的参数
    strcpy(str,"hello");
    prinf("%s",str); //顺利输出
    free(str);  //记得释放内存
}

 

对于理解“指向指针的指针”概念困难的同学,可以用函数返回值来传递内存。但是我似乎没有看出这种方法比代码而简单多少。

代码三

View Code
char* GetMemory(int num)
{
    char *p = (char *)malloc(sizeof(char) * num);
    return p;
}

int main()
{
    char *str = NULL;
    str = GetMemory(100);
    strcpy(str,"hello");
    printf("%s",str);
    free(str); //记得释放内存呀
}

在写函数返回值来传递内存时,有人会不小心把return语句写错。比如返回“栈内存”的指针。(用人话讲 就是返回一个 在函数体内的局部变量,之所以不能这么干是因为函数执行结束时,这些局部变量所存储的空间会被释放)比如你不能这么写:

代码四

View Code
 1 char* GetString(void)
 2 {
 3     char p[] = "hello world";
 4     return p; 
 5 }
 6 
 7 int main()
 8 {
 9     char *str = NULL;
10     str = GetString();
11     strcpy(str,"hello");
12     printf("%s",str);
13 }

运行出来会打印出奇怪的东西,反正不是我们要的结果。编译的时候第4行会有警告,function returns address of local variable(函数返回了一个局部变量的地址) 。调试会发现执行str = GetString()后str不是NULL指针,也不是“hello world”。如果改成下面这段代码呢?

代码五

View Code
char* GetString(void)
{
    char *p = "hello world";
    return p;
}

int main()
{
    char *str = NULL;
    str = GetString();
    printf("%s",str);
}

运行是可以的,但是这么写代码是有问题的,GetString函数里面的“hello world”是一个常量字符串,位于静态存储区域,它在程序生命期间恒定不变,无论什么时候调用这个函数,它返回的都是“hello world”。

 

最后整理 如何预防野指针

“野指针”不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if语句对它不起作用。
 
(1)指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。例如
char *p = NULL;
char *str = (char *) malloc(100);
 
(2)指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。
(3)指针操作超越了变量的作用范围。这种情况让人防不胜防。

 

posted @ 2012-08-28 11:40  仰望星空的耕田人  阅读(504)  评论(0编辑  收藏  举报