总结程序BUG原因

本文深入探讨程序BUG产生的五大主要原因,包括变量未初始化、内存泄漏、空值检测遗漏、条件判断错误及volatile使用不当,旨在帮助开发者避免常见陷阱,提升代码质量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写程序多年,创造了很多BUG,总结一下这些BUG的原因。


一、清零


这个原因很常见,特别是底层驱动代码,不可避免需要一些全局变量,对于这些全局变量的清零要注意。
一般可分为:
1.应该清零的地方没有清零。
    或者是忘记清零,或者是误以为不需要清零。
2.不该清零的地方却清零了。
    这会导致变量结果得不到累积。
函数越长,或是越想节省临时变量一个变量多次无关使用,逻辑混乱,越是容易出现这类错误。所以个人认为,函数设计准则:短小精悍,功能单一,尽量可重入。

 

二、内存释放


通常,成功申请一段内存后,假如忘记了释放,结果就是可用内存越来越少,最后程序完蛋。
一般而言,内存申请函数与内存释放函数是在一个函数内,必须要成对使用。这是一对“函数对”。类似的还有一些系统中的进出临界区函数对(FreeRTOS:taskENTER_CRITICAL()/taskEXIT_CRITICAL()),进出中断通知函数对(uCOS:OSIntEnter()/OSIntExit()),FATFS中的打开关闭文件函数对(f_open()/f_close())。
我想,或许IDE可以提供一种特殊的宏(或assert或其他东西)供程序员使用,做到代码预编译时,一旦发现没有成对使用自定义的函数对,就会提示警告。
假设此宏形式为__CHECK_PAIRS(p) 
这时,自定义一对函数对:
void f_ENTER()
{
    __CHECK_PAIRS(f_ENTER) ;
    //DO SOMETHING
}
void f_EXIT()
{
    __CHECK_PAIRS(f_EXIT) ;
    //DO SOMETHING
}
那么,在一个函数中,我们使用了f_ENTER(),而没有f_EXIT(),IDE预编译时会通过__CHECK_PAIRS检测到此情况,发出警告提示。
即使这样不能完全检测出这些错误(比如函数中有循环使用此类函数),但依然能够提供不少帮助。(有些瞎扯了)

 

三、空值检测


创建一个对象,或者申请一段内存,都是有可能失败的。正常来说应该做一个判断,保证程序正常处理。
char *p=malloc(10);
if(NULL == p)
{
//DO SOMETHING
}

 

四、判断相等


1.“=”与“==”误用。在C中,一不小心把“=”当做“==”。很多IDE都会提示warning,不过有些IDE没有任何提示。
2.浮点数。在C中,浮点数判断相等最好不要使用“==”,可以这么做:两数相减,判断结果的绝对值是否小于某个很小的数。
3.字符串,引用类型的比较。在一些高级语言如C#、java中,“==”与equals方法不是一回事。“==”是判断引用的地址是否一致,也就是两者是否是同一个对象;equals则是比较“内容”。

 

五、volatile


编译器帮你优化程序,但可能修改了你的原本逻辑思路。
使用volatile修饰的变量,意味着“每次都要去原始地址读,别偷懒去使用上次的备份”。该用volatile的地方必须要用,否则你有机会发现:某个变量明明应该变了啊怎么没有变化呢?
多任务包括中断函数共享的标志变量,硬件寄存器映射的变量,是volatile的使用场合。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值