来源于《高质量C/C++编程》的几道经典面试题

题目1:非法访问+内存泄漏

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 函数会有什么样的结果?
结果:在这里插入图片描述
解析:

void Getmemory(char* p)//用p来接收str的数据,p是形参,形参是实参的一份临时拷贝
{
	p = (char*)malloc(100);//给p开辟一个100字节的空间。
	//还有这里开辟了空间后,并没有释放,造成内存泄漏。
}
void test(void)
{
	char* str = NULL;
	Getmemory(str);//将str这个指针传过去,相当于传值过去,并不是传址输入,对形参的改变并不会影响实参。
	strcpy(str, "hello world");//这里的str还是空指针,并没有空间给它拷贝,形成NULL非法访问,这里就出错了。
	printf(str);
}
int main()
{
	test();
	return 0;
}

1.str传给p的时候,p是str的临时拷贝,有自己的独立空间,当GetMemory函数内部申请了空间后,地址放在p中,str仍然是NULL。当Getmemory函数返回之后,strcpy拷贝的时候,形成了非法访问。
2.在Getmemory函数内部,动态申请空间,但是没有释放,造成内存泄漏

正确做法1:

void Getmemory(char** p)//str是一级指针,&str就是二级指针
{
	*p = (char*)malloc(100);//*p就相当于str,就是给str开辟一个100字节的空间
}
void test(void)
{
	char* str = NULL;
	Getmemory(&str);//这里进行传址输入,利用形参修改实参
	strcpy(str, "hello world");//这里的str就拥有了100字节的空间了
	printf(str);
	free(str);//释放空间
	str=NULL//手动置NULL
}
int main()
{
	test();
	return 0;
}

正确做法2:

char* Getmemory(char* p)//那Getmemory函数返回值就要改成char *类型接收指针
{
	p = (char*)malloc(100);
	return p;//将p返回
}
void test(void)
{
	char* str = NULL;
	str=Getmemory(str);//这里用指针str来接收Getmemory函数内部形参开辟的空间
	strcpy(str, "hello world");
	printf(str);
	free(str);//释放空间
	str=NULL//手动置NULL
}
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);
}
int main()
{
	test();
	return 0;
}

请问运行Test 函数会有什么样的结果?
结果:
在这里插入图片描述
解析:

char* Getmemory(void)
{
	char p[] = "hello world";//创建一个数组p,里面存放着字符串
	return p;//返回数组名,也就是返回了数组首元素的地址
}
void test(void)
{
	char* str = NULL;
	str = Getmemory();//Getmemory函数的返回值用str来接收
	//数组p的首元素地址用str来接收
	//但要注意的是,p数组是在Getmemory内部创建,创建在栈区,出了函数,这个空间就要返回给操作系统,不再受指针p操控。
	//所以str虽然得到了数组的首元素地址,但这片空间已经不再属于数组空间了,所以形成了非法访问
	printf(str);//打印str指向的字符
}
int main()
{
	test();
	return 0;
}

这个问题统称为返回栈空间地址问题
就是在栈上开辟的空间,并将指向这块空间的地址返回,但这块空间的使用者发现改变,不再是原先的使用者了,而再根据地址找到这块空间来访问就会出问题。
这个要按自己的实际需求来正确修改。

题目3:内存泄漏

void Getmemory(char** p, int num)
{
	*p = (char*)malloc(num);
}

void test(void)
{
	char* str = NULL;
	Getmemory(&str, 100);
	strcpy(str, "xiao tao");
	printf(str);
}
int main()
{
	test();
	return 0;
}

请问运行Test 函数会有什么样的结果?
在这里插入图片描述
解析:
这个题目跟第一题的修改后的题目差不多

void Getmemory(char** p, int num)
{
	*p = (char*)malloc(num);//开辟100个字节空间给*p  *p就是str
	//所以给str开辟了100字节的空间
}

void test(void)
{
	char* str = NULL;
	Getmemory(&str, 100);//传址输入,可以通过对形参修改而修改实参
	strcpy(str, "xiao tao");//对str指向的空间进行拷贝
	printf(str);//打印拷贝后的空间内容
	//最最重要的一点是,空间申请后,释放呢?这里没有释放所以最后会造成内存泄漏
	free(str);//释放内存
	str = NULL;
}
int main()
{
	test();
	return 0;
}

题目4:非法访问

void test(void)
{
	char* str = (char*)malloc(100);
	strcpy(str, "xiao tao");
	free(str);
	if (str != NULL)
	{
		strcpy(str, "666");
		printf(str);
	}
}
int main()
{
	test();
	return 0;
}

请问运行Test 函数会有什么样的结果?
在这里插入图片描述
解析:

void test(void)
{
	char* str = (char*)malloc(100);//开辟100个字节的空间
	strcpy(str, "xiao tao");//给指向srt的空间进行拷贝
	free(str);//释放空间
	//free的功能是将原先指向这块空间的指针与这块空间之间的联系断开,这块空间不再首这个指针调控,回归到操作系统,供有需要的使用
	//而free释放空间后并不会将原先指向这块空间的指针置为空指针,还是指向原先的地方,所以下面的操作就进行下去了
	//所以这个指针又去访问那块空间让其被覆盖成666,这就造成非法访问了
	if (str != NULL)//如果str不为空指针进行下面操作
	{
		strcpy(str, "666");
		printf(str);//打印指向str那块空间的内容
	}
}
int main()
{
	test();
	return 0;
}

正确做法:在不改变原意的基础上修改:

void test(void)
{
	char* str = (char*)malloc(100);//开辟100个字节的空间
	strcpy(str, "xiao tao");//给指向srt的空间进行拷贝
	free(str);//释放空间
	str = NULL;//释放空间后手动置为NULL,让下面的操作无法进行
	if (str != NULL)//如果str不为空指针进行下面操作
	{
		strcpy(str, "666");
		printf(str);//打印指向str那块空间的内容
	}
}
int main()
{
	test();
	return 0;
}
  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小陶来咯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值