test1:
void GetMemory(char* p)
{
p = (char*)malloc(100);
}
void Test(void)
{
char* str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}
int main()
{
Test();
return 0;
}
请问执行上面代码,会出现什么结果?
解析:运行该段代码时,程序会崩溃
答案:调用Test函数时,在Test函数内部又调用Getmemory函数,即使在Getmemory函数内部申请空间,返回的该空间的起始地址给p,然而p并未返回,str仍为NULL。拷贝 "hello world"到str内部,将会导致程序崩溃。
改正:可以将p申请的空间返回。
test2
char* GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char* str = NULL;
str = GetMemory();
printf(str);
}
int main()
{
Test();
return 0;
}
请问执行上面代码,会出现什么结果?
解析:运行该程序时,可能会出现乱码。
这是因为在调用GetMemory函数时,p是一个数组,在栈空间上申请内存,即使返回p,用str指针来接收,此时str指针指向了p的地址,但是在调用Getmemory完成后,p所在的空间会被释放,所以str指向的空间是一块未知的空间,使用该空间也造成了非法访问,空间内的内容我们是不知道的。
改正:可以将char p[] 改成char *p, 这样创建的空间就算再常量区,而不是再栈区,出了该函数也不会再销毁该空间。
test3
void GetMemory(char** p, int num)
{
*p = (char*)malloc(num);
}
void Test(void)
{
char* str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
int main()
{
Test();
return 0;
}
请问执行上面代码,会出现什么结果?
解析: 运行该段代码,会打印hello。
就算能运行hello,但是在使用完申请的空间后,并没有释放申请的空间,会造成内存泄露。
改正:free(str); str = NULL;
test4
void Test(void)
{
char* str = (char*)malloc(100);
strcpy(str, "hello");
free(str);
if (str != NULL)
{
strcpy(str, "world");
printf(str);
}
}
int main()
{
Test();
return 0;
}
请问执行上面代码,会出现什么结果?
解析:输出world。
然而,即使会打印world,str是在使用一块不属于自己的空间,因为在第一次拷贝hello之后,对str指向的空间进行了释放,该空间不再属于str,str已经成为野指针。但是str仍然存着这块释放掉的空间的起始地址,所以进入判断语句的时候,该语句不再起到能够阻止str进入的效果,随后str使用的空间是属于操作系统的空间,非法使用空间会有很大的安全隐患。
改正:在free(str);后面加上 str = NULL;
最后:附上c内存分配的几个主要区域。