目录
一.常见的动态内存错误
1.对NULL指针的解引用操作
void test() { int* p = (int*)malloc(INT_MAX);//INT_MAX是代表最大整数值的宏,INT_MAX= 2147483647 *p = 20; free(p); }
如果malloc函数开辟内存失败就会返回NULL,在这串代码中,malloc由于需要开辟的空间过大,所以返回了NULL,那么*p就是在对NULL指针的解引用,碰到这种情况程序就会崩溃。
2.对动态开辟的内存空间越界访问
void test() { int i = 0; int *p = (int *)malloc(10*sizeof(int));//开辟10个整形空间 if(NULL == p) { exit(EXIT_FAILURE);//EXIT_FAILURE代表文件异常退出。stdio.h中:#define EXIT_FAILURE 1 } for(i=0; i<=10; i++) { *(p+i) = i; } free(p); }
显然,当i=0的时候越界访问了。
3.对非动态内存开辟的空间进行free释放
void test() { int a = 100; int *p = &a; free(p); }
动态内存开辟的空间是属于堆区,非动态内存开辟的空间属于栈区,栈区是属于系统管理的,绝对不能free。当以动态内存开辟的形式向系统申请空间时,实际上是将内存中未使用的内存地址返回,然后再将这块空间标记为已使用,free实际上是将那块地址重新标记为未使用,对一块已经是未使用的地址再次标记未使用是肯定不行的。
4.free释放动态内存开辟空间的一部分
void test() { int *p = (int *)malloc(100); p++; free(p); }
这串代码中,开辟空间后由于p++,所以p不再指向空间的起始位置,所以也不能free。
5.多次free同一块动态内存
void test() { int *p = (int *)malloc(100); free(p); free(p); }
也是相当于将同一块空间二次标记为未使用。
6.忘记释放动态开辟的内存空间
void test() { int *p = (int *)malloc(100); if(NULL != p) { *p = 20; } } int main() { test(); while(1); }
不再使用的动态内存空间忘记释放的话会造成内存泄漏。
二.笔试题分享
题目1:
//请问程序运行的结果是什么?为什么会出现这种情况? 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; }
程序运行后肯定是会崩溃的,调运函数GetMemory后str并未发生变化,其中依旧是NULL,GetMemory中的p只是str的一份临时拷贝,对p进行动态内存开辟不会影响到str。所以程序运行到strcpy处就会崩溃。并且没有对内存是否开辟成功进行判断,没有手动释放开辟的空间。
题目2:
//程序运行的结果是什么?为什么会出现这种情况? char* GetMemory(void) { char p[] = "hello world"; return p; } void Test(void) { char* str = NULL; str = GetMemory(); printf(str); } int main() { Test(); return 0; }
显然,程序最终输出的肯定是乱码。p数组的作用域只在GetMemory中存在,当出了GetMemory时p会被销毁,最后返回的p指向不明,因此打印出来的肯定是乱码。并且没有对内存是否开辟成功进行判断,没有手动释放开辟的空间。
题目3:
//程序运行的结果? void GetMemory(char** p, int num) { *p = (char*)malloc(num); } void Test(void) { char* str = NULL; GetMemory(&str, 100); strcpy(str, "hello"); printf(str); }
程序最终成功打印hello,上诉代码中最终开辟动态内存的是*p也就是str,即str开辟内存后p会在GetMemory结束后销毁,所以对str没有影响,所以最终打印hello,但由于未对开辟内存进行成功与否的判断,未手动释放开辟的内存,所以依旧存在问题。
题目4:
//运行结果?为社么? 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; }
运行结果肯定是打印world。因为这串代码虽然free了str,但并未将str置空,导致str是一个野指针,因此if判断始终成立。
最后,感谢你的观看!