内存使用问题应该注意这五点

来源:互联网 发布:最短路径算法 最优 编辑:程序博客网 时间:2024/05/21 10:00

* 在程序员的世界里,“内存”这个词被比作“雷区”,因为很多时候程序代码编译能通过,但是结果却不是我们想要的,或者编译的时候中断,这时候,我们便开始绞尽脑汁地调试,想尽各种办法,经过七七四十九天之后,突然眼前一亮,oh my god!居然是一个语句中内存使用错误。所以,与其花费那么多时间调试,还不如好好想想如何尽量少出现这种错误。下面,我总结了在内存使用时的常见错误。*

1.对NULL指针进行解引用操作

内存使用最常见的错误就是忘记检查所请求的内存分配是否成功,此外,在函数实现的时候,如果有指针变量作为形参,没有对参数进行NULL判断。下面给出几点建议:
(1)使用malloc()的时候,一定要使用if()语句进行判断,如code1所示。当然,你也可以按照自己的方式进行指针检查。

//code1:    int *ptr = (int *)(10 * sizeof(int));    if (NULL == ptr)        exit(EXIT_FAILURE);

(2)在函数的入口处,若形参为指针变量,则用assert()检查指针是否为空,形如assert(NULL!=ptr);
(3)定义一个指针变量时,一定要将其初始化,可以为某个值的地址,可以为NULL。

2.对内存的使用越界

对内存的使用越界,比如你申请了一块空间,每次使用一定的字节,若算法出错,导致使用了你所申请的空间的下一个空间。这个时候,这块空间有可能是不可访问的,对于这种情况你还是很幸运的,至少编译器会有错误提示。然而,如果这块空间正好存放了其他有用的数据,那么你的做法将会改变这块空间的内容,这个问题是非常让人头疼的,因为在大多数情况下,编译器是不会报错的,而且还能显示结果,只是结果很可能不是你想要的。来看code2,先自己想想结果是什么?

//code2#include<stdio.h>#include<stdlib.h>int main(){    int i = 0;    int arr[10];    for (i = 0; i <= 12; i++)    {        arr[i] = 0;        printf("%d ", arr[i]);    }    system("pause");    return 0;}

来看结果
这里写图片描述

简直让人大吃一惊,出现了死循环。我们知道,栈是向下增长的,而数组元素的地址是依次升高的,在vs2013编译器下,变量i和数组arr中间空了2个字节的大小(注意,在其他编译器下很可能不是两个字节,比如vc6.0或者gcc)。当arr[9]被赋值为0时,循环会继续进行,此时,(arr+10)、(arr+11)(arr+12)这三快内存都被赋值为0,但是,注意到arr+12这块内存空间正好是变量i的空间,当我们执行(arr+12)=0;的时候,变量i又从新变成了0。这样,明白了为什么会死循环了吧。

3.释放并非动态分配的内存

在第2中情况下,假如这块空间是使用malloc()在堆上开辟的,当你想要用free()释放的时候,程序便会中断(我的环境是在Windows平台的vs2013下)。如code2所示。

//code3#include<stdio.h>#include<stdlib.h>#include<string.h>int main(){    char *p = "hello world!";    char *ptr = NULL;    int len = strlen(p);    ptr = (char *)malloc(len*sizeof(char));    if (NULL == ptr)        exit(0);    strcpy(ptr, p);    printf("%s\n", ptr);    system("pause");    return 0;}

这里写图片描述

结果的确是我们想要的,可是,这里出现什么问题了呢?注意到代码中没有用free()释放,这时我们在printf(“%s\n”, ptr);语句后面加上free(ptr)会发生什么了?如下图所示:
这里写图片描述

当我们调试的时候,会发现程序终止在free(ptr)处,因为strlen()计算长度的时候并没有把‘\0’加进去,但是在拷贝的时候,把‘\0’也放到了ptr所指向的内存中,但是很明显空间不够用,这时‘\0’放在了我们申请的空间的下一个字节的地方。当我们使用free()释放的时候,企图把不是动态分配的空间也给释放掉,这时非法的,所以程序发生了中断。

4.释放动态分配内存的一部分

在使用free()时,传递给free函数的指针必须是一个从malloc、calloc或realloc函数返回的指针,并且不能企图释放这块内存的一部分。比如free(ptr+2),其中ptr是由malloc分配的内存。但是,relloc函数可以缩小一块动态分配的内存,可是有效地释放它尾部的部分内存。

5.使用了已被释放的内存

有时候,当我们的代码量非常大的时候,会容易犯这样的错误,在free掉某个内存之后,我们依然对其进行使用。这种情况下,在vs2013软件中会出现如下图所示的中断。
这里写图片描述

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 自考毕业证出生日期错误怎么办 成考没有学位证怎么办 评职称学历认证怎么办 国家不承认学历怎么办 高考分数错了怎么办 签合同了不想干怎么办 贵港教育小学插班生怎么办 学校宿舍限瓦怎么办 苹果锁屏后wifi断开怎么办 兼职一天不给钱怎么办 五月孩子掉床怎么办 孩子五月份掉床怎么办 郑州怎么办暂住证凭条 郑州居住证凭条怎么办 宿舍虫子咬人怎么办 is语音注册频繁怎么办 苹果id注销了怎么办 网站突然打不开了怎么办 谷歌邮箱打不开怎么办 360借款无力承担怎么办 公司被收购期权怎么办 创业板连续亏损怎么办 国企合并后员工怎么办 资金密码忘记了怎么办? 大华电子秤称重不准怎么办 股票暂停上市散户怎么办 入股公司赔钱了怎么办 家里被虚报脱贫怎么办 技术入股想退股怎么办 想开店没有资金怎么办 想开店资金不够怎么办 要开店没资金怎么办 想开店缺少资金怎么办 刚刚开店没有资金怎么办 有专利没钱投资怎么办 肉牛养殖没资金怎么办 入股分红想撤资怎么办 入股后想退股怎么办 土地使用权到期后怎么办 员工辞职扣工资怎么办 公司老板要跑路不发工资怎么办