繁体   English   中英

如何调试这个C代码

[英]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)。但真的没有得到它如何导致溢出?

如果ab的总和大于UINT_MAX ,则a+b可能溢出, UINT_MAXunsigned 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 )。 这会导致溢出,因此结果是错误的。 例如,如果ab都等于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;

对于ab某个值, a + bunsigned 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签名中,整数溢出是未定义的行为和未签名的环绕。

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

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