题目1:
大家可以先看看这段代码有没有什么问题:
void GetMemory(char *p)
{
p = (char *)malloc(100);
}
void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}
如图:有两个警告,要是不顾及这些警告强制运行,就会使系统崩溃。
我画了个图简单分析一下原因:(这里假设起始地址是0x11223344)
这段代码由main函数调用Test函数。
Test里面的运行步骤:
- 创建一个指针变量赋值NULL
- 将str也就是NULL传参给GetMemory
- 用p指针接收过来的NULL
- 创建空间并将起始地址传给p,这个时候p里面存的是起始地址,str里面存的是NULL
- GetMemory结束运行,但没有返回任何值,这个时候p里面存的还是起始地址,str里面存的还是NULL
- 用strcpy函数将字符串赋值给str所指向的空间,但是str是空指针,上一篇文章里面说过对空指针解引用会使系统崩溃。
这就是这段程序的主要问题。
解决方法:
方法1:将p存放的地址返回
char* GetMemory()
{
char* p = (char*)malloc(100);
return p;
}
void Test(void)
{
char* str = NULL;
str=GetMemory();
strcpy(str, "hello world");
printf(str);
}
int main()
{
Test();
return 0;
}
方法2:用二级指针存放str的地址,利用str的地址来改变str的值
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;
}
题目2:
这个不是关于动态内存的,只是与上一个题有点类似。
char *GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(str);
}
先来看一下运行结果:
它打印了一堆烫烫烫,OK,他为什么这么烫呢?
原因:
这段代码是用数组创建的的空间,要知道数据跟变量一样,有着自己的作用域与生命周期,他在GetMemory函数中创建,那GetMemory运行结束就会释放这块空间。
当返回Test函数时,p的数组以及释放完成,这个时候我们把p存放的地址传给str,依旧可以找到这块空间,但是这块空间已经不属于这段代码,str就是野指针,对str进行操作就是访问野指针,形成非法访问,从而打印一串乱码。
题目3:
void GetMemory(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
大家看一下这段代码,发现跟我在上面写的方法二几乎一模一样,那他有什么问题呢?
运行后发现,它可以正常打印,并且编译器没有出现任何警告和报错。
但是他忘了最重要一点,开辟的动态内存使用完后要及时释放,不然会在一些情况下造成一些严重的后果。
在写这个题目时我也发现我上面的那两段代码没有及时释放空间,希望你们能引以为戒,防止跟我一样出现这种低级的错误。
题目4:
void Test(void)
{
char *str = (char *) malloc(100);
strcpy(str, "hello");
free(str);
//-------------------
if(str != NULL)
{
strcpy(str, "world");
printf(str);
}
}
这段代码在分隔符前面没什么问题,但是他在释放空间后没有给str赋值NULL,而又对str进行了判断以及操作。
要知道释放空间后str指向的内容已经释放,str这时已经是一个野指针了,对野指针进行相关操作就是非法访问,程序就会直接中断报错。
--------------------------------------------分隔符
这篇是对前面几篇内容的练习,可以让刚接触到动态内存分配的人对它做一个回顾与复习。
感谢各位的观看,有错请指正,谢谢。