博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
常见的内存错误及其对策
阅读量:5020 次
发布时间:2019-06-12

本文共 2461 字,大约阅读时间需要 8 分钟。

操作系统复习

特点

编译器不能自动发现这类错误,通常是在程序运行时才能捕捉到

时隐时现,无明显症状

分类

1 内存分配未成功,却使用了它

起因 没有意识到内存分配会不成功 编程新手容易犯

解决对策 在使用内存之前,检查指针是否为空指针(NULL)

char *p = (char *) malloc(100);  if (p == NULL)     {        printf("No enough memory!\n");        exit(0);     }
View Code

 

 

2 内存分配成功,但是尚未初始化就引用它

起因 没有初始化的观念 误以为内存的默认值全为0

实际情况 

内存的缺省初值究竟是什么并没有统一的标准。但是对于全局变量和静态变量如果没有手工初始化,编译器会将其初始化为零,而对栈内存和堆内存则不作任何处理。

另外,VC在Debug和Release状态下在初始化变量时所做的操作是不同的。Debug是将每个字节位都赋值成0xcc,以有利于调试。而Release的赋值是直接从内存中分配的,内容近似于随机。所以如果在没有初始化变量的情况下去使用它的值,就会导致问题发生。

解决对策 即使是赋0值也不可省略,不要嫌麻烦

 

 

3 内存分配成功,并且已经初始化,但操作越过了内存的边界

内存分配成功,并且已经初始化,但操作越过了内存的边界 例如:使用数组时经常发生下标“多1”或者“少1”的操作

解决对策: 在for语句中,注意循环次数不要搞错

访问越界会出现什么结果?

首先,它并不会造成编译错误! 就是说,C/C++的编译器并不判断和指出代码“访问越界”了。此外,数组访问越界在运行时,它的表现是不定的,有时似乎什么事也没有,程序一直运行(当然,某些错误结果已造成);有时,则是程序一下子崩溃。

 

 

4 忘记了释放内存,造成内存泄漏

忘记释放内存,造成内存泄漏(Memory Leak) “内存泄露”一词类似“原料泄露” 泄露出去的原料不能被利用,导致生产过程中原料不足。好比借东西不还 如果申请来的内存不用,别的程序也不能用,就好像这块内存泄露出去一样,造成浪费。

以下这段小程序演示了堆内存发生泄漏的情形:

void MyFunction(int nSize){char* p= new char[nSize];if( !GetStringFrom( p, nSize ) ){MessageBox(“Error”);return;}…//using the string pointed by p;delete p;}
View Code

当函数GetStringFrom()返回零的时候,指针p指向的内存就不会被释放。这是一种常见的发生内存泄漏的情形。程序在入口处分配内存,在出口处释放内存,但是C函数可以在任何地方退出,所以一旦对分支处理不完整或者错误处理不当的话,就会发生内存泄漏。虽然函数体内的局部变量在函数结束时自动消亡,但是局部的指针变量所指向的内存并不会被自动释放。

含有这种错误的函数每被调用一次就丢失一块内存。刚开始时系统的内存充足,可能看不到错误,但终有一次程序突然死掉,系统出现提示:内存耗尽。

动态内存的申请与释放必须配对,如果程序在入口处动态申请了内存,那么在程序的每个出口处都必须释放该内存空间。

解决对策

在需要的时候才malloc,并尽量减少malloc的次数 malloc的执行效率就不高,过多的malloc使程序性能下降 能用自动变量解决的问题,就不要用malloc来解决 malloc一般在大块内存分配和动态内存分配时使用

重复使用malloc申请到的内存

尽量让malloc和与之配套的free在一个函数或模块内 尽量把malloc集中在函数的入口处,free集中在函数的出口处

 

 

5 释放了内存,却继续使用它

free(ptr);        if (ptr != NULL) //不起作用{    …}
View Code

起因: 指针所指的内存被释放以后,并不表示指针会消亡 其地址仍然不变(非NULL),只是该地址对应的内存是垃圾 指向垃圾内存的指针是“野指针”

有三种情况:

(a) 程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面。

(b) 函数的return语句写错了,注意不要返回指向“栈内存”的“指针”或者“引用”,因为该内存在函数体结束时被自动销毁。

(c) 使用free释放了内存后,没有将指针设置为NULL。导致产生“野指针”,即不是NULL指针,而是指向“垃圾”内存的指针。“野指针”是很危险的,因为使用if语句进行判断对它不起作用。

char *p = (char *) malloc(100);strcpy(p, “hello”);free(p);        // p 所指的内存被释放,但是p所指的地址仍然不变…if(p != NULL)    // 没有起到防错作用{    strcpy(p, “world”);    // 出错}
View Code

解决对策

尽量把malloc集中在函数的入口处,free集中在函数的出口处

如果free不能放在函数出口处,则指针free后立即设置为NULL

不要把局部变量的地址作为返回值返回,因为该内存在函数体结束时被自动销毁

指针要么初始化为NULL,要么是其指向合法的内存

非法内存操作

起因

内存分配未成功,却使用了它

内存分配成功,但是尚未初始化就引用它

内存分配成功,并且已经初始化,但操作越过了内存的边界

释放了内存,却继续使用它

基本特征

代码访问了不该访问的内存地址

后果

几乎全是由指针混乱导致的

少数情况下,如在硬件驱动程序中的内存问题会造成操作系统的死亡

转载于:https://www.cnblogs.com/vincentqliu/p/6858475.html

你可能感兴趣的文章
php中strlen和mb_strlen的区别
查看>>
数据库【mongodb篇】练习操作
查看>>
第十二周学习进度
查看>>
淘宝网6个质量属性的场景分析:
查看>>
PJzhang:kali linux安装网易云音乐、Visual Studio Code、skype
查看>>
CentOS7下JSP连接Mysql
查看>>
文件包含
查看>>
Android 更新升级下载 自定义Updates 兼容版
查看>>
第一次提交 nacos 代码
查看>>
【MVC学习笔记01】初窥奥秘
查看>>
SAM初步
查看>>
测试用例评审
查看>>
关于getClass().getClassLoader()
查看>>
Mysql常用的存储引擎
查看>>
树状列表
查看>>
三元操作符的类型务必一致
查看>>
drbd mysql
查看>>
c复习过程随笔八
查看>>
MySQL学习
查看>>
使用delete删除指针(转)
查看>>