简体   繁体   English

如何调试这个C代码

[英]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 . 如果ab的总和大于UINT_MAX ,则a+b可能溢出, UINT_MAXunsigned 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. 例如,如果ab都等于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 . 对于ab某个值, a + bunsigned 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签名中,整数溢出是未定义的行为和未签名的环绕。

如果ab足够高以产生高于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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM