三、常见动态内存错误🥹:
1.对 NULL 指针的解引用操作(一定要判断空指针!):
int main() { int* p = (int*)malloc(5 * sizeof(int)); int i = 0; for (i = 0; i < 5; i++) { *(p + 1) = 0; } return 0; }
上面代码中,在 malloc 执行后,没有对 p 指针进行检查,因为 malloc 也可能失败,失败时会返回一个空指针,如果是这样,那下面就是对空指针进行解引用操作,这样是不合适的。
2.对动态内存空间的越界访问:(要检查是否越界!)
int main() { int i = 0; int* p = (int*)malloc(10 * sizeof(int)); if (NULL == p) { perror("malloc"); return 1; } for (i = 0; i <= 10; i++) { *(p + i) = i;//当i是10的时候越界访问 } free(p); p = NULL; }
上述代码,当 i 等于10的时候就会造成越界访问,越界访问最终会导致程序挂掉.
3.对非动态内存空间使用 free 函数(free函数只针对堆区的内存!):
int main() { int a = 10;//栈区 int* p = &a; free(p); return 0; }
&emspl 需要注意free针对的是堆区上的空间,而上述代码中的 p 指针指向一个整型变量,整型变量是在栈区申请的空间
4.使用 free 函数释放动态内存空间的一部分(free释放时要从头释放!):
int main() { int* p = (int*)malloc(5 * sizeof(int)); if (p == NULL) { perror("malloc"); return 1; } int i = 0; for (i = 0; i < 5; i++) { *p = 0; p++; } free(p); }
上面代码中的 p 指针,在经历过多次 p++ 之后就不再指向这 5 55 个整型的起始地址了,此时再去free 就会出问题。
避免此类错误的方法是,在使用指针前保存好初始指向,并在进行动态内存释放时释放完整的动态内存空间。
5.对同一块动态内存空间多次释放(一定要记得在释放空间后把指针置空!):
int main() { int* p = (int*)malloc(10 * sizeof(int)); free(p); //...(在中间又进行了很多其它操作之后,忘记了已经释放过动态内存空间,并进行了重复释放) free(p); //重复释放动态内存空间 p = NULL; return 0; }
如上面代码,在程序的最后对 p 指针 free 了两次,此时程序就会报错。本质原因就是对同一块动态内存多次释放程序会报错。但是如果在第一个 free 的后面把 p 指针赋为空指针,然后再 free§ 就没有任何问题了。
6.不释放动态内存空间(内存泄漏):
void test() { int* p = (int*)malloc(10 * sizeof(int)); if (p != NULL) { *p = 20; //判断非空后进行使用 } //使用后没有释放动态内存空间,在程序终止前该动态内存空间都将无法被释放,将会逐渐蚕食计算机系统的内存 } int main() { test(); while (1); //为了演示内存泄漏,使程序永不终止 return 0; }
避免此类问题的方法是,永远记住,使用一个释放一个,使用结束立刻释放。
总结:
通过今天内容的学习,相信各位小伙伴们已经掌握了动态内存的开辟、释放与动态修改,并且已经对动态内存空间的各项使用注意事项有了一定的认知和了解。希望小伙伴们在下去以后,在对动态内存空间的使用和管理中一定要慎之又慎,尽最大可能避免出现类似的相关问题。
更新不易,辛苦各位小伙伴们动动小手,三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!