[英]How to debug the This C code
在网站上阅读一些问题时,我遇到了问题需要调试的问题
unsigned int a, b, c;
/* a and b are assume to have some values */
c = (a + b) / 2; // <- There is a bug in this st
What is the bug? and how you debug it?
一些答案说它可能导致溢出(c =(a + b)/ 2)。但真的没有得到它如何导致溢出?
如果a
和b
的总和大于UINT_MAX
,则a+b
可能溢出, UINT_MAX
是unsigned int
的最大值。 例如,
unsigned a = 1;
unsigned b = UINT_MAX;
printf("%u\n", (a+b)/2);
打印0
。
如果要查找没有溢出的两个unsigned int
的平均值,请执行
c = a/2 + b/2 + (a % 2 & b % 2);
(或(a%2 + b%2)/2
,或(a%2 && b%2)
,或((a&1) & (b&1))
等)
如果a
和/或b
非常大,则a + b
可能超过无符号整数的最大大小(请参阅limits.h
文件中的MAX_UINT
)。 这会导致溢出,因此结果是错误的。 例如,如果a
和b
都等于0x80000000,则结果在32位算术中为0,而不是预期的结果0x80000000。
要解决它,你可以使用这样的东西:
c = a/2 + b/2 + (a % 2 == 1 && b % 2 == 1);
如果您知道b
大于a
那么您可以使用这个稍微简单的版本:
c = a + (b - a) / 2;
阅读这篇文章,了解这个bug如何在可能流行的语言中出现在二进制搜索算法中的信息(尽管它讨论的是signed int
而不是unsigned int
):
正如其他人所说:
unsigned int a, b, c;
c = (a + b) / 2;
对于a
和b
某个值, a + b
在unsigned int
无法表示。
一个非常类似的情况导致标准Java二进制搜索实现( binarySearch
函数)中的一个着名的错误。
请参阅2006年着名的Joshua Blosh博客文章:
“额外,额外 - 阅读所有关于它:几乎所有的二进制搜索和合并都是破碎的” http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html
摘录:
错误在这一行:
6:int mid =(低+高)/ 2;
再向下:
那么修复bug的最佳方法是什么? 这是一种方式:
6:int mid = low +((high - low)/ 2);
请注意,在Joshua帖子中, high
>= low
并且还使用了int
对象,但Java将签名溢出视为包装。 在C签名中,整数溢出是未定义的行为和未签名的环绕。
如果a
和b
足够高以产生高于unsigned int
可表示的最大值的a + b
,则可能导致溢出。
如果只在C中声明变量而不初始化它,则会得到一个不可预测的值 。 a和b可以是某些值,它们当前位于内存中的地址中。
您可以在Eclipse CDT中调试C代码
http://www.eclipse.org/cdt/
使用此IDE,您可以使用C anc C ++进行编程,它包含GDB调试器。
http://www.gnu.org/software/gdb/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.