动态内存管理笔试题
一
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;
}
程序运行结果:没有输出,奔溃
解释:str传递给GetMemory函数是值传递方式,所以GetMemory函数参数p是str的一份临时拷贝;在GetMemory函数内部动态申请的空间,首地址赋给了参数p指针,因为形参的生命周期跟局部变量一样,出了函数便自动销毁,所以GetMemory函数返回之后,指针p便销毁,使得动态开辟的100个字节的内存存在内存泄漏,无法释放;同时外部的str因为是值传递,所以并没有改变,依然是NULL,strcpy把“hello world”拷贝到空指针中,明显出错,print(str)也出错。
正确修改1:
char* GetMemory(char* p) //函数返回类型改为char*
{
p = (char*)malloc(100);
return p; //将p指针返回
}
void Test(void)
{
char* str = NULL;
str = GetMemory(str); //用str指针接收返回值,这样str指针就指向了动态开辟的100个字节的空间
strcpy(str, "hello world");
printf(str); /*该打印方式没问题,printf("hello world")只是把字符串的首地址即'h'的地址传给printf函数,便可以进行打 印,同理,str指向的也是'h'的地址,所以可以打印*/
free(str); //最后释放动态开辟的空间
}
正确修改2:
void GetMemory(char** p) //参数改为二级指针
{
*p = (char*)malloc(100); //参数p存放的是str的地址,*p便得到str,即用str指向malloc开辟的空间
}
void Test(void)
{
char* str = NULL;
GetMemory(&str); //要想改变变量的值,就要传地址过去
strcpy(str, "hello world");
printf(str);
free(str);
}
二
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函数内开辟了一块连续的空间,用来存放字符串,数组名指向“hello world”字符串的首地址,return p时返回的的确是指向该字符串所在空间的首地址,但该空间因为是在栈上开辟的,所以函数结束时该空间就被释放了,还回给了操作系统,当指针str接收到该地址时==(因为地址其实就是个标签,门牌号,不是什么变量,所以函数结束也可以返回)==,地址里存放的内容可能已经被系统给更改了,不再是字符串,也可以说是一块未知的内存空间,所以打印出来的是乱码。
三
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
考查点:free函数不会自动将指针置空
解释:虽然程序能运行,也有结果出来,但代码已经出现了非法访问内存的错误;在动态申请完空间后,并没有对str指针进行判空操作,这也是一个小错误,不够严谨;strcpy函数完成操作后,内存放入了“hello”字符串,随后free(str),释放掉了刚刚动态开辟的100个字节的内存空间,还回给了操作系统,但指针并没有置空,所以依然指向着刚才的空间,if判断为真,再次往这块空间拷贝“world”字符串,此时已经对内存进行了非法访问,最后输出该空间内容。
正确修改:
void Test (void)
{
char* str = (char* ) malloc (100);
if(str == NULL) //对动态内存是否申请成功进行判断
{
printf("申请动态内存失败\n");
return;
}
strcpy(str,"hello");
free (str) ;
str == NULL; //手动将指针置空,防止后续操作对非用户空间进行访问和操作
if (str != NULL)
{
strcpy(str, "world" );
printf(str) ;
}
}