C语言动态内存经典笔试题分析
文章目录
- C语言动态内存经典笔试题分析
- 1. 题目一
- 2. 题目二
- 3. 题目三
- 4. 题目四
1. 题目一
void GetMemory(char *p){p = (char *)malloc(100);}
void Test(void){char *str = NULL;GetMemory(str);strcpy(str, "hello world");printf(str);}
运行Test函数会有什么结果?
代码运行时会崩溃
上述代码中出现的问题
- malloc开辟的空间没有释放,内存泄漏
- 代码会崩溃,即使GetMemory函数返回,str依然为NULL
- GetMemory函数无法把malloc开辟的100个字节带回来
TIP:上述代码中的printf(str);没有错,与printf(“abcdef”); printf(“%s”,str);一样,都是将数组的首元素地址传给kbd>printf
代码出现的主要问题是GetMemory函数返回,str依然为NULL
分析:
传给GetMemory函数的只是str中的值,并不是str的地址,使用为传值调用,传值调用形参的改变并不会改变实参,形参只是实参的临时拷贝,所以str中的值不会改变,在使用strcpy时,对NULL指针解引用了,导致程序崩溃
上述代码的修改:
void GetMemory(char** p)
{*p = (char*)malloc(100);
}
void Test(void)
{char* str = NULL;GetMemory(&str);strcpy(str, "hello");printf(str);free(str);str = NULL;
}
2. 题目二
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函数会有什么结果?
正常打印hello
分析:
与题目一类似,不过这段代码时将,str的地址传给了GetMemory函数,函数形参使用二级指针存放指针的地址,并将开辟好的空间的地址赋值给p,也就是str,代码并没有明显问题,并不会像代码一一样崩溃
只不过这段代码没有释放malloc开辟的空间,会导致内存泄漏
上述代码的修改:
void GetMemory(char** p, int num)
{*p = (char*)malloc(num);
}
void Test(void)
{char* str = NULL;GetMemory(&str, 100);strcpy(str, "hello");printf(str);free(str);str = NULL;
}
3. 题目三
char* GetMemory(void)
{char p[] = "hello world";return p;
}
void Test(void)
{char* str = NULL;str = GetMemory();printf(str);
}
运行Test函数会有什么结果?
代码打印的结果是不确定的
分析:
这段代码错就错在返回了局部变量的地址,局部变量的生命周期在出作用域就结束了,也就是在调用完GetMemory函数之后,p就被销毁了,还给了操作系统,在下面用指针接收了局部变量的地址时,这个指针就是野指针,代码打印会出不确定的结果
可以简化下这段代码:
int* test()
{int n = 10;return &n;
}
int main()
{int* ret = test();printf("hello\n");printf("%d", *ret);return 0;
}
打印出的结果为不确定的
分析:
上述代码就是明显返回了局部变量的地址,如果没有 printf(“hello\n”);这段的话,代码虽然能正常运行但是不代表没错,printf(“hello\n”);这段的话破坏了函数的栈帧空间,导致打印的值不确定
在运行代码的时候,main函数开辟一块空间,再为TestTest函数开辟一快空间,再为TestGetMemort函数开辟一快空间,GetMemort函数中有一个字符数组p,并且返回p的地址,数组名就是首字符地址,调用GetMemort函数结束,GetMemort函数被销毁,还给了操作系统,当在打印数组之前,出现了其他代码,就会破坏函数的栈帧空间,导致打印的值为不确定的
4. 题目四
void Test(void)
{char* str = (char*)malloc(100);strcpy(str, "hello");free(str);if (str != NULL){strcpy(str, "world");printf(str);}
}
代码运行结果正常打印world
运行结果没错不代表结束没错
分析:
在上述代码中,使用strcpy将“hello”拷贝到str中,然后使用free释放了malloc开辟的空间,空间没了,但是空间的地址还在,str没有置NULL,此时str就是野指针,对野指针进行访问就是非法访问,因为野指针指向的一块不属于它的空间