笔记-常见的动态内存错误
1.对NULL指针的解引用操作
void test()
{
int *p = (int *)malloc(INC_MAX/4);//当p的值为NULL时,就会有问题。
*p = 20;
free(p);
}
malloc函数返回值需要判断。
2.对动态开辟空间的越界访问
void test()
{
int i = 0;
int *p = (int *)malloc(10*sizeof(int));
if(NULL == p)
{
exit(EXIT_FAILURE);
}
for(i = 0; i <= 10; i ++)
{
*(p + i) = i;//当i = 10时越界访问
}
free(p);
}
3.对非动态开辟内存使用free释放
void test()
{
int a = 10;
int *p = &a;
free(p);//释放不了,程序会崩!!!
}
4.使用free释放一块动态开辟内存的一部分
void test()
{
int *p = (int *)malloc(100);
p ++;
free(p);//p不再指向动态内存的起始位置
}
5.对同一块动态内存进行多次释放
对人协作的情况下,要注意其他人是否已经释放,避免重复释放和不释放的情况。
void test()
{
int *p = (int *)malloc(sizeof(100));
free(p);
free(p);//重复释放
}
6动态开辟内存忘记释放
在一般情况下,如果不使用free释放,程序结束之后,也会由操作系统回收。
但是在未使用free函数,程序又无法终止的情况下,这块开辟的内存无法被找到和使用,就会产生内存泄漏的情况。
void test()
{
int *p = (int *)malloc(sizeof(100));
if(NULL != p)
{
*p = 20;
}
}
int main()
{
test();
while(1);//程序无法结束,而且也没有使用free函数释放,所以会造成内存泄露。
}
几个经典的笔试题
第一道:
void GetMemory(char *p)
{
p = (char *)malloc(100).
//p是str的一份临时拷贝,所以在退出函数的时候会被销毁,但是由malloc申请的空间还没有被free释放,所以导致空间虽然存在,但是无法通过p找到并使用,由此产生了内存泄漏的现象。
}
void test()
{
char *str = NULL;
GetMemory(str);
//传递的是变量本身,所以是传值调用,返回后str仍然是空指针。
strcpy(str,"hello world");
//将hello world通过解引用操作拷贝到str当中,但是对NULL指针进行解引用就导致了程序崩溃。
printf(str);
//使用printf函数对字符串进行打印的时候,可以直接将地址传进去
}
修改方式:
1.
char *GetMemory()
{
char *p = (char *)malloc(100).
return p;
}
void test()
{
char *str = NULL;
str = GetMemory();
strcpy(str,"hello world");
printf(str);
}
2.
void GetMemory(char **p)
{
*p = (char *)malloc(100);
}
void test()
{
char *str = NULL;
GetMemory(&str);
strcpy(str,"hello world");
printf(str);
}
第二道:返回栈空间地址的问题
char *GetMemory(void)
{
char p[] = "hello world";
//此函数内部创建的数据是在栈区的临时数据,在退出函数后将归还给内存,但是这里将这块空间的地址返回了
return p;
}
void test()
{
char *str = NULL;
str = GetMemory();
//因为传给str的地址所指向的空间内容已经归还了,所以里面的内容可能已经被修改了,此时并不再是hello world 了,所以通过str访问并打印出来的结果是未知字符。
printf(str);
}
第三道:
void test()
{
char *str = (char *)malloc(100);
strcpy(str,"hello");
free(str);
//释放了str动态申请的空间后,空间已经被归还给操作系统,但是str仍然指向空间首段地址。
if(str != NULL)
{
strcpy(str,"world");//这里对已经释放的空间进行解引用操作,造成了非法访问
printf(str);//虽然是非法访问,但是结果是可以输出world的
}
}
解决办法就是在free函数后面,将str指针置空。