导致程序异常重启的原因

    类C类软件大多都支持通过指针对内存进行访问,使用不当很容易造成程序运行异常或异常重启的问题,记录下可能的原因和解决方案:

1、任务、线程堆栈溢出。

     函数中使用大数组局部变量,超大结构体变量,容易导致堆栈溢出。

    解决办法:

     1.1、将大数组局部变量,超大结构体变量更改为指针变量,使用动态内存申请获取存储空间。

      1.2、如果函数没有重入问题,可以简单的将大数组局部变量,超大结构体变量放到函数体外作为全局变量进行定义。

     识别溢出的方法:

     1.1、如果编译器有堆栈溢出检查功能,使能该功能。

      1.2、自行实现堆栈溢出检查功能(在栈顶极限位置写入特定值,运行时检查此数值是否改变)

2、动态内存泄露,动态内存耗尽。

      通过在动态内存分配释放函数里增加调试代码,统计分配和释放数据,观察是否存在内存耗尽问题。

3、访问未初始化的指针,导致非法地址访问或异常改写其他内存地址内容。

       此类问题,可以通过代码审查发现,代码量很大时,比较难排查。

       变量初始化属于编程习惯问题,可以养成是变量必初始化的习惯,避免此类问题。

4、数组写入越界。

        在数组使用上,写入越界,很隐蔽,却很容易造成程序异常或重启。比如自定义如下函数:

   无返回值    示例函数(  字符串类型  提示语 )

        静态的 整数类型  计数=0;

        字符类型   缓冲区[30];

        sprintf(  缓冲区, "%(整数) :%(字符串)", ++计数, 提示语 );

        。。。。

 }

为节省对堆栈空间的耗用, 定义了够用就好的缓冲区, 在使用中,调用此函数,只要传入的提示语比较短,都没什么问题。 

如果提示语又是其他函数构造的,其长度大部分时候不会过长,测试运行没问题,偶尔时候长度长了一些,就可能造成 缓冲区 数组越界写入,改写其他内存。 

另外,随着计数数字的增大,其转换为字符串所占的字节数也越来越多,存在溢出隐患。

5、标准C库用法错误

     标准C库并不是一个容错性,健壮性很好的函数库,对其的调用时需要非常注意输入参数,通常要对输入参数做一些异常判断,才能保证C库函数运行正常。而C语言又是函数式语言,其代码通常都离不开对标准C库的调用,输入参数检查多,代码冗长,编程效率低, 新人不喜欢。 新人通常喜欢高效,不做任何检查,直接调用C库,因为C库内又没有容错处理,所以时常导致各种异常发生,这也就是C语言不好学习,不好掌握的原因之一,也是新人很多时候编码没有埋雷多的原因之一。例如:

短整数类型  年=2025;
字节类型 月=1,日=12;
printf("缺省年月日:%d-%d-%d, 标志=%x\n",年,月,日,标志 );// 缺省年月日:2025-1-12
printf("请输入当前日期:" );
scanf("%d-%d-%d",&年,&月,&日);   //用法有问题,参数类型不匹配。

        上述示例代码中最后一行的用法就不正确,格式字符 %d 会将后面提供的 地址参数作为一个整数空间进行填充,而其空间定义的是字节类型或短整数类型,都比整数类型所占空间小,导致写入溢出,可能改写临近内存空间的数值。这种写法并不避免出错或异常,这还和处理器的字节序,编译优化处理相关。即使当前测试运行不出错,不保证未来代码修改,变量定义语句前后增加其他变量之后是否还能运行正常。 正确的用法应该是:

整数类型  年=2025;
整数类型 月=1,日=12;
printf("缺省年月日:%d-%d-%d, 标志=%x\n",年,月,日,标志 );
printf("请输入当前日期:" );
scanf("%d-%d-%d",&年,&月,&日);

 

        此外还有 strcpy(目标地址,源地址); 如果源地址是0地址,就会出现非法地址访问错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值