题目一:
void GetMemory(char*p){
p=(char*)malloc(100);
}
void Test(void){
char*str=NULL;
GetMemory(str);
strcpy(str,"hello world");
printf(str);
}
请问运行Test函数会有什么样的结果?
答案:非法访问
【解析】进入Test函数之后,先初始化了str的指针指向NULL,后调用了GetMemory函数,跳出函数后,进行字符串拷贝后打印。有人觉得传参没有问题,动态开辟也没有问题,那么问题在哪呢?
问题在于GetMemory调用后,并没有将str的地址传过去,所以并不能改变str的信息,char*p只是str的一份临时拷贝,Getmemory函数中为p动态开辟了一份空间,p指向了这份空间的首地址,但函数结束后这份动态开辟的空间就会被释放,str没有发生任何改变,还是指向空指针。这是用strcpy函数对str解引用后赋值,就是非法访问了。
如果要修改的话,我们可以这样做:
void GetMemory(char**p){//二级指针接受指针的地址
*p=(char*)malloc(100);
}
void Test(void){
char*str=NULL;
GetMemory(&str);//将str指针的地址传过去
strcpy(str,"hello world");
printf(str);
}
题目二:
char*GetMemory(void){
char p[]="hello world";
return p;
}
void Test(void){
char*str=NULL;
str=GetMemory();
printf(str);
}
请问调用Test函数会发生什么样的结果?
答案:打印乱码
【解析】进入Test函数之后,初始化了str指针指向空,后调用GetMemory函数,GetMemory函数返回了字符串的首地址,之后打印。那么有什么问题呢?
问题在于,程序运行完后p数组被销毁,而此时str指向了该空间的首地址,销毁后str成了野指针,在打印后只会打印出乱码。这是典型的返回栈空间地址的问题,在操作系统中一共有三个区域,分别是堆区、栈区和静态区。
栈区存储局部变量、函数形式的参数等;
堆区存储malloc、free、realloc的动态内存;
静态区存储全局变量、静态变量;
我们的p存储在栈区中,栈空间地址在函数结束后会被释放。所以str最终成了野指针。
题目三:
void GetMemory(char**p,int num){
*p=(char*)malloc(num);
}
void Test(void){
char*str=NULL;
GetMemory(&str,100);
strcpy(str,"hello");
printf(str);
}
请问运行Test函数会有什么样的后果?
答案:内存泄漏
【解析】通过我们之前将的动态内存管理直到,动态开辟的内存使用后必须free掉,否则会发生内存泄漏,程序报错。所以我们只需要在print发(str)后加上free(str);str=NULL;就可以了。
题目四:
void Test(void){
char*str=(char*)maloc(100);
strcpy(str,"hello");
free(str);
if(str!=NULL){
strcpy(str,"world");
printf(str);
}
}
请问运行Test函数会有什么样的结果?
答案:非法操作
【解析】在if语句之前,就已经将str的空间释放掉了,那么str就成为了一个野指针。此时进入if语句,将“world”拷贝到str里面,解引用野指针就会报错,即非法操作。
我们可以这样修改:
void Test(void){
char*str=(char*)malloc(100);
strcpy(str,'"hello");
if(str!=NULL){
strcpy(str,"world");
printf(str);
}
free(str);
str=NULL;
}