[英]How to debug the This C code
While reading some question on a site I came across below question where ac question needs to be debug 在网站上阅读一些问题时,我遇到了问题需要调试的问题
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?
Some of the answer saying it could cause overflow(c=(a+b)/2).but really didn't get how it cause overflow? 一些答案说它可能导致溢出(c =(a + b)/ 2)。但真的没有得到它如何导致溢出?
a+b
may overflow if the sum of a
and b
is larger than UINT_MAX
, the maximum value for an unsigned int
. 如果
a
和b
的总和大于UINT_MAX
,则a+b
可能溢出, UINT_MAX
是unsigned int
的最大值。 Eg, 例如,
unsigned a = 1;
unsigned b = UINT_MAX;
printf("%u\n", (a+b)/2);
prints 0
. 打印
0
。
If you want to find the average of two unsigned int
s without overflow, do 如果要查找没有溢出的两个
unsigned int
的平均值,请执行
c = a/2 + b/2 + (a % 2 & b % 2);
(or (a%2 + b%2)/2
, or (a%2 && b%2)
, or ((a&1) & (b&1))
, etc.) (或
(a%2 + b%2)/2
,或(a%2 && b%2)
,或((a&1) & (b&1))
等)
If a
and/or b
are very large then a + b
could exceed the maximum size of an unsigned integer (see MAX_UINT
in the limits.h
file). 如果
a
和/或b
非常大,则a + b
可能超过无符号整数的最大大小(请参阅limits.h
文件中的MAX_UINT
)。 This would cause an overflow and so the result would be wrong. 这会导致溢出,因此结果是错误的。 For example if
a
and b
are both equal to 0x80000000 the result would be 0 in 32-bit arithmetic, rather than expected result 0x80000000. 例如,如果
a
和b
都等于0x80000000,则结果在32位算术中为0,而不是预期的结果0x80000000。
To solve it you could use something like this instead: 要解决它,你可以使用这样的东西:
c = a/2 + b/2 + (a % 2 == 1 && b % 2 == 1);
If you know that b
is greater than a
then you could use this slightly simpler version: 如果您知道
b
大于a
那么您可以使用这个稍微简单的版本:
c = a + (b - a) / 2;
Read this article for information about how this bug appeared in binary search algorithms in may popular languages (though it talks about signed int
rather than unsigned int
): 阅读这篇文章,了解这个bug如何在可能流行的语言中出现在二进制搜索算法中的信息(尽管它讨论的是
signed int
而不是unsigned int
):
As other say: 正如其他人所说:
unsigned int a, b, c;
c = (a + b) / 2;
a + b
can be not representable in an unsigned int
for some value of a
and b
. 对于
a
和b
某个值, a + b
在unsigned int
无法表示。
A very similar situation led to a famous bug in the standard Java binary search implementation ( binarySearch
function). 一个非常类似的情况导致标准Java二进制搜索实现(
binarySearch
函数)中的一个着名的错误。
See this famous Joshua Blosh blog post in 2006: 请参阅2006年着名的Joshua Blosh博客文章:
"Extra, Extra - Read All About It: Nearly All Binary Searches and Mergesorts are Broken" http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html “额外,额外 - 阅读所有关于它:几乎所有的二进制搜索和合并都是破碎的” http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html
Excerpts: 摘录:
The bug is in this line:
错误在这一行:
6: int mid =(low + high) / 2;
6:int mid =(低+高)/ 2;
further down: 再向下:
So what's the best way to fix the bug?
那么修复bug的最佳方法是什么? Here's one way:
这是一种方式:
6: int mid = low + ((high - low) / 2);
6:int mid = low +((high - low)/ 2);
Note that in Joshua post, high
is >= low
and also int
objects were used but Java treats signed overflow as wrapping. 请注意,在Joshua帖子中,
high
>= low
并且还使用了int
对象,但Java将签名溢出视为包装。 In C signed integer overflows are undefined behavior and unsigned wraparound. 在C签名中,整数溢出是未定义的行为和未签名的环绕。
如果a
和b
足够高以产生高于unsigned int
可表示的最大值的a + b
,则可能导致溢出。
If you only declare a variable in C without initialize it, it gets an unpredictably value . 如果只在C中声明变量而不初始化它,则会得到一个不可预测的值 。 a and b can be some value which is currently at the adress they get in the memory.
a和b可以是某些值,它们当前位于内存中的地址中。
You can debug C code in Eclipse CDT 您可以在Eclipse CDT中调试C代码
http://www.eclipse.org/cdt/ http://www.eclipse.org/cdt/
With this IDE you can program in C anc C++ and it contains the GDB debugger. 使用此IDE,您可以使用C anc C ++进行编程,它包含GDB调试器。
http://www.gnu.org/software/gdb/ http://www.gnu.org/software/gdb/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.