题目一
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
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;
}
判断上面代码能否打印出"hello world"
问题:
调用GetMemory函数后,p指向了地址0x0012ff40,str仍然是NULL,出了GetMemory函数后,p空间还给操作系统。执行strcpy的时候,是要把hello world拷贝到str中,而str是空指针,不能对空指针进行解引用,最后程序崩溃。
修改1:
GetMemory采用值传递,无法将开辟的空间地址返回放在str中,调用结束后str仍然是NULL。因此,想要获取内存得使用址传递。最后释放空间,并置为空指针。
void GetMemory(char** p)
{
*p = (char*)malloc(100);
}
void Test(void)
{
char* str = NULL;
GetMemory(&str);
strcpy(str, "hello world");
printf(str);
free(str);
str=NULL;
}
int main()
{
Test();
return 0;
}
修改2:
将p的地址返回给str
char* GetMemory(char* p)
{
p = (char*)malloc(100);
return p;
}
void Test(void)
{
char* str = NULL;
str = GetMemory(str);
strcpy(str, "hello world");
printf(str);
free(str);
str = NULL;
}
int main()
{
Test();
return 0;
}
题目二:
char* GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char* str = NULL;
str = GetMemory();
printf(str);
}
int main()
{
Test();
return 0;
}
执行上述代码的结果是
并不是hello world
问题(返回栈空间地址):
假设返回p的地址是0x0012ff40给到str,而除了GetMemory函数后,申请的p空间还给了操作系统,无法再找到p的内容,str成为了野指针,如果重新申请空间后,0x0012ff40可能被申请的空间覆盖,再想找这个空间的值后可能就是随机值了。
修改:
将p变为静态变量,出函数不销毁。
char* GetMemory(void)
{
static char p[] = "hello world";
return p;
}
void Test(void)
{
char* str = NULL;
str = GetMemory();
printf(str);
}
int main()
{
Test();
return 0;
}
类似问题
int* f1(void)
{
int x = 10;
return (&x);
}
接收此函数的返回值的指针则成为了野指针。
题目三:
void GetMemory(char** p, int num)
{
*p = (char*)malloc(num);
}
void Test(void)
{
char* str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
int main()
{
Test();
return 0;
}
问题:
没用对开辟的空间进行释放,可能会存在内存泄漏问题。
题目四:
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;
}
虽然程序能正常运行,但是代码仍存在问题。
问题:
释放str后,str就是野指针,而后面又要将hello拷贝到str中去,就会发生非法访问。
因此需要把str置为NULL。
类似问题:
int* f2(void)
{
int* ptr;
*ptr = 10;
return ptr;
}
没有对ptr进行初始化,ptr是随机值,解引用后就会发生非法访问。