C--有关内存的思考
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//结果段错误,因为str指向空,传递的是指针变量,要传变量地址才可以
void getmemory0(char *p)
{
p = (char *)malloc(100);
}
void test(void)
{
char *str = NULL;
getmemory0(str);
strcpy(str,"hello world");
printf("%s\n",str);
}
//结果正确,传递了指针变量的地址
void getmemory1(char **p)
{
*p = (char *)malloc(100);
}
void test1(void)
{
char *str = NULL;
getmemory1(&str);
strcpy(str,"hello");
printf("%s\n",str);
free(str);
}
//返回栈内存,内存在函数结束时消亡,str不指向空,但也不指向hello
//结果可能正确,也可能是乱码
char *getmemory2(void)
{
char p[] = "hello world";
return p;
}
void test2(void)
{
char *str = NULL;
str = getmemory2();
printf("%s\n",str);
}
//str变为野指针,修改动态内存区的内容,结果可能正确,也可能错误
//后果难以预料,非常危险
void test3(void)
{
char *str = (char *)malloc(100);
strcpy(str,"hello");
free(str);
if(str != NULL)
{
strcpy(str,"world");
printf("%s\n",str);
}
}
int main(int argc, char *argv[])
{
test();
//test1();
//test2();
//test3();
return 0;
}
分析:
1.test()中:
如果函数的参数是一个指针,不要指望用该指针去申请动态内存。原因:编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是_p,编译器使_p = p,如果函数体内的程序修改了_p的内容,就导致了p的内容作相应的修改,这就是指针可以用作输出参数的原因。但是,本例中,_p申请了新的内存,只是把_p所指向的内存地址改变了,但是p丝毫未变。所以getmemory并不能输出任何东西。
运行结果:程序崩溃,str仍然为NULL,strcpy运行错误。
2.test1()中:
如果非得要用指针参数去申请内存,那么应该传递“指向指针的指针”,即传&str。记得释放内存free(str)。
运行结果:能输出hello。
3.test2()中:因为return语句返回了指向"栈内存"的指针,因为该内存在函数结束时自动消亡;执行str = getmemory()后,str不再是NULL指针,但str的内容也不再是“hello world”。
运行结果:可能是乱码,也可能是正确,str的内容是垃圾。
4.test3()中:
if(str != NULL)进行防错处理是没有用的,因为free/delete只是把指针所指向的内存给释放掉了,但并没有干掉指针本身,str被free以后,其地址仍不变(非NULL),只是该地址对应的内存是未知的,str成了野指针。
运行结果:出错,改动动态内存区的内容,后果难以预料,非常危险。