面试题之GetMemory关于内存的详解

681 阅读2分钟

题目一:

void GetMemory(char *p){
    p = (char *)malloc(100);
}
void Test(void){
    char *str = NULL;
    GetMemory(str);//目的是通过此函数给str空间
    strcpy(str, "hello world");
    printf(str);
}

出现问题:
在函数内部修改形参并不能真正的改变传入实参的值

代码解析:

  1. 调用 GetMemory(str) 后,str并未产生变化,依然是NULL。只是改变的str的一个拷贝的内存的变化
  2. strcpy( str, "hello world" ); 程序运行到这将产生错误(不能拷贝)。
  3. p = (char *) malloc( num ); 后判断内存是否申请成功,应加上:
if ( p != NULL ){
	//进行申请内存成功处理
}
  1. 内存没有释放

改正:
方法1:(推荐使用这种方法)
改变函数的参数((char **p)变为二级指针)

void GetMemory(char **p, int num) {  
	//p是str地址的一个副本,p指向的值改变,也就是str的值改变。 
	*p = (char *)malloc(sizeof(char) * num); 
} 
void Test(void){ 
	char *str=NULL; 
	GetMemory=(&str); //把str的地址传进去 
	strcpy(str,"hello world"); 
	printf(str); 
 	free(str);
 	str = NULL;
}

方法2:
改变函数的返回值(指针函数:返回值为指针的函数)

char *GetMemory(){ 
	char *p=(char *)malloc(100); 
	return p; //返回指向堆空间的指针 
} 
void Test(void){ 
	char *str=NULL; 
	str=GetMemory();
	strcpy(str,"hello world"); 
	printf(str); 
	free(str);
 	str = NULL; 
}

题目二:

char *GetMemory(void){
    char p[] = "hello world";
	return p; 
}
void Test(void){
    char *str = NULL;
    str = GetMemory();
    printf(str);
}

出现问题:
p[]数组为函数内的局部自动变量,在函数返回后,内存已经被释放!(这是很多程序员常犯的错误,其根源在于不理解变量的生存期)用调试器逐步跟踪Test,发现执行str=GetMemory() 语句后str不再是NULL指针,但是str的内容不是“hello world”,而是垃圾。

题目三:

void GetMemory(char **p, int num){
    *p = (char *)malloc(num);
}
void Test(void){
    char *str = NULL;
    GetMemory(&str, 100);
    strcpy(str, "hello");
    printf(str);
}

出现问题:

  1. GetMemory避免了题目二的问题,传入GetMemory的参数为字符串指针的地址,但是在GetMemory中执行申请内存及赋值语句
    *p = (char *) malloc( num ); 后未判断内存是否申请成功,应加上:
if ( *p != NULL ){
 //进行申请内存成功处理
} 
  1. Test函数中也未对malloc的内存进行释放。

题目四:

void Test(void){
    char *str = (char *) malloc(100);
    strcpy(str, “hello”);
    free(str);
    if(str != NULL)
    {
        strcpy(str, “world”);
        printf(str);
	}
}

出现问题:

  1. 在执行char *str = (char *) malloc(100); 后未进行内存是否申请成功的判断
  2. 在free(str)后未置str为空,导致可能变成一个“野”指针,应加上: str = NULL;
内存释放后,指针不置为NULL的后果!
  1. 释放后未置为NULL,继续判断if(NULL != p)为真、而进行错误的操作~~
  2. 使用野指针,后果未定义。
    运气好的话,崩了。
    运气不好,程序用了不正确的数据,出了错误结果,你都不知道为什么,哪出错了。