> 文章列表 > 笔记-常见的动态内存错误

笔记-常见的动态内存错误

笔记-常见的动态内存错误

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指针置空。