C语言中史上最愚蠢的Bug

标签: C/C++语言 杂项资源 编程语言 轶事趣闻 C++ | 发表时间:2011-08-26 10:17 | 作者:陈皓 E. Liu
出处:http://coolshell.cn

本文来自“The most stupid C bug ever”,很有意思,分享给大家。我相信这样的bug,就算你是高手你也会犯的。你来看看作者犯的这个Bug吧。。

首先,作者想用一段程序来创建一个文件,如果有文件名的话,就创建真正的文件,如果没有的话,就调用?tmpfile()?创建临时文件。他这段程序就是HTTP下载的C程序。code==200就是HTTP的返回码。

else if (code == 200) {     // Downloading whole file
    /* Write new file (plus allow reading once we finish) */
    g = fname ? fopen(fname, "w+") : tmpfile();
}

但是这个程序,只能在Unix/Linux下工作,因为 Microsoft 的?tmpfile()的实现?居然选择了 C:\ 作为临时文件的存放目录,这对于那些没有管理员权限的人来说就出大问题了,在Windows 7下,就算你有管理员权限也会有问题。所以,上面的程序在Windows平台下需要用不同的方式来处理,不能直接使用Windows的tmpfile()函数。

于是作者就先把这个问题记下来,在注释中写下了FIXME:

else if (code == 200) {     // Downloading whole file
    /* Write new file (plus allow reading once we finish) */

    // FIXME Win32 native version fails here because
    //   Microsoft's version of tmpfile() creates the file in C:\
    g = fname ? fopen(fname, "w+") : tmpfile();
}

然后,作者觉得需要写一个跨平台的编译:

FILE * tmpfile ( void ) {
#ifndef _WIN32
    return tmpfile();
#else
    //code for Windows;
#endif
}

然后,作者觉得这样实现很不好,会发现名字冲突,因为这样一来这个函数太难看了。于是他重构了一下他的代码——写一个自己实现的tmpfile() – w32_tmpfile,然后,在Windows 下用宏定义来重命名这个函数为tmpfile()。(陈皓注:这种用法是比较标准的跨平台代码的写法)

#ifdef _WIN32
  #define tmpfile w32_tmpfile
#endif

FILE * w32_tmpfile ( void ) {
    //code for Windows;
}

搞定!编译程序,运行。靠!居然没有调用到我的w32_tmpfile(),什么问题?调试,单步跟踪,果然没有调用到!难道是问号表达式有问题?改成if – else 语句,好了!

if(NULL != fname) {
    g = fopen(fname, "w+");
} else {
    g = tmpfile();
}

问号表达式不应该有问题吧,难道我们的宏对问号表达式不起作用,这难道是编译器的预编译的一个bug?作者怀疑到。

现在我们把所有的代码连在一起看,并比较一下:

能正常工作的代码

#ifdef _WIN32
#  define tmpfile w32_tmpfile
#endif

FILE * w32_tmpfile ( void ) {
    code for Windows;
}

else if (code == 200) {     // Downloading whole file
    /* Write new file (plus allow reading once we finish) */
    // FIXME Win32 native version fails here because
    //     Microsoft's version of tmpfile() creates the file in C:\
    //g = fname ? fopen(fname, "w+") : tmpfile();
    if(NULL != fname) {
        g = fopen(fname, "w+");
    } else {
        g = tmpfile();
    }
}

不能正常工作的代码

#ifdef _WIN32
#  define tmpfile w32_tmpfile
#endif

FILE * w32_tmpfile ( void ) {
    code for Windows;
}

else if (code == 200) {     // Downloading whole file
    /* Write new file (plus allow reading once we finish) */
    // FIXME Win32 native version fails here because
    //    Microsoft's version of tmpfile() creates the file in C:\
    g = fname ? fopen(fname, "w+") : tmpfile();
}

也许你在一开始就看到了这个bug,但是作者没有。所有的问题都出在注释上:

/* Write new file (plus allow reading once we finish) */
// FIXME Win32 native version fails here because
//     Microsoft's version of tmpfile() creates the file in C:\

你看到了最后那个C:\吗?在C中,“\” 代表此行没有结束,于是,后面的代码也成了注释。这就是这个bug的真正原因

而之所以改成if-else能工作的原因是因为作者注释了老的问号表达式的代码,所以,那段能工作的代码成了:

/* Write new file (plus allow reading once we finish) */
// FIXME Win32 native version fails here because Microsoft's version of tmpfile() creates the file in C:    //g = fname ? fopen(fname, "w+") : tmpfile();
if(NULL != fname) {
    g = fopen(fname, "w+");
} else {
    g = tmpfile();
}

我相信,当作者找到这个问题的原因后,一定会骂一句“妈的”!我也相信,这个bug花费了作者很多时间!

最后,我也share一个我以前犯的一个错。

我有一个小函数,需要传入一个int* pInt的类型,然后我需要在我的代码里 把这个int* pInt作除数。于是我的代码成了下面的这个样子:

float result = num/*pInt;
….

/*  some comments */

-x<10 ? f(result):f(-result);

因为我在我当时用vi编写代码,所以没有语法高亮,而我的程序都编译通过了,但是却出现了很奇怪的事。我也不知道,用gdb调式的时候,发现有些语句直接就过了。这个问题让我花了很多时间,最后发现问题原来是没有空格导致的,TNND,下面我用代码高亮的插件来显示上面的代码,

float result = num/*pInt;
....

/*  some comments */

-x<10 ? f(result):f(-result); 

Holly Shit!  我的代码成了:

float result = num-x<10 ? f(result):f(-result);

妈的!我的这个错误在愚蠢程度上和上面那个作者出的错误有一拼。

(全文完)

相关文章

相关 [语言 中史 愚蠢] 推荐:

C语言中史上最愚蠢的Bug

- E. Liu - 酷壳 - CoolShell.cn
本文来自“The most stupid C bug ever”,很有意思,分享给大家. 我相信这样的bug,就算你是高手你也会犯的. 首先,作者想用一段程序来创建一个文件,如果有文件名的话,就创建真正的文件,如果没有的话,就调用?tmpfile()?创建临时文件. 他这段程序就是HTTP下载的C程序.

保持愚蠢

- ewen - 阮一峰的网络日志
Steve Jobs有一句名言:. 直译就是"保持饥饿,保持愚蠢". 也就是说,乔布斯告诫年轻人,永远怀有强烈的求知欲,以及虚心求教的态度. 我原以为,这句话只是一句励志格言. 今天看到一篇文章,才意识到它其实是一种纠正人类心理缺陷的对策.   * 96%的癌症病人,认为自己比其他癌症病人健康.   * 93%的司机,认为自己的安全意识高于普通司机.

愚蠢到极点的国家电网

- chaim - 牛博山寨头条
      有一张国家银行的卡,明明里面有钱,却取不出来. 柜台服务员说,帮你查可以,但你要告诉我你一共花过多少钱. 光告诉我花过多少钱还不行,还要告诉我目前结余多少,这样我才能帮你查出此卡是否还有余额.       你见过这么荒谬愚蠢的银行吗.       嘿嘿,我也没见过,但我见过类似的愚蠢荒谬国的“准银行”——国家电网.

Google关闭实验室太愚蠢

- K.L. - 师北宸的网络日志
9月3日,Google首席执行官拉里·佩奇宣布,关闭产品实验室(Google Labs). 2004年4月1日,当Google推出它的电邮软件Gmail,并声称拥有1GB容量时,全世界的人都以为Google在逗大家玩儿呢. 结果到了4月2日人们发现,这不是骗人的. 这款从诞生开始,至今七年多以来一直是世界上最优秀没有之一的电邮软件,最初是工程师利用百分之二十的时间在Google实验室玩出来的.

聪明的专制,和愚蠢的专制

- leplay - 在地铁站
扔开别的不说,站在tg的立场上,总归是为tg延续了执政生命,算是聪明的做法. 时至今日,只能说是一蟹不如一蟹. 活人还没救毕,立地掩埋;不见任何体恤动作,只讲“限期领赔偿金”;事故原因尚未调查清楚,催命通车;显见是人祸,愣说是天灾. 但这种硬,是愚蠢到极点,完全是折损tg阳寿的硬. 如果老邓在台,估计拔出驳壳枪就把铁盗部的头儿给毙了.

Google前首席信息官建议“做愚蠢的事”

- QQ - Solidot
Shawn the R0ck 写道 "前Google首席信息官Douglas Merrill在澳大利亚的悉尼举行CA expo 2011上分享了一些他在搜索引擎巨人工作时学到的管理诀窍. 在所有列表中最重要的是:"不要害怕做愚蠢的事情". Merrill回忆道"在Google早期的硬件大多是从垃圾堆里偷出来的,而在这些垃圾硬件上构建可靠的软件系统,所有人都认为我们不应该构建自己的硬件系统,这简直是只有傻瓜才会做的事情,但所有人都错了.

RIM CEO曾愚蠢判断:平板没前途 iPhone不足惧

- 洞箫 - cnBeta.COM
美国科技博客BusinessInsider周末撰文回顾了黑莓制造商RIM两位联席CEO关于苹果和Android系统的愚蠢判断,正是领导层的错误决策导致了RIM目前陷入困境. 自从2007年1月,史蒂夫•乔布斯(Steve Jobs)首次发布iPhone以来,RIM的股票已经下跌了65%. RIM股价下跌的原因很简单:他们没有充分了解苹果开发的产品,iPhone智能手机可不止能发电子邮件那么简单.

对股价12种最愚蠢(最危险)的认识

- UO - laoba1梁军儒的BLOG
1、股价已经下跌这么多了,不可能再跌了.     这种说法听起来似乎很有道理. 我敢打赌,在宝丽来公司股票从最高的143. 5美元一路下跌的过程中,当股价下跌了1/3时,那些一直持有这只股票的投资者一定在不断地重复着这句话:“股价已经下跌这么多了,不可能再跌了. ”宝丽来是一家实力雄厚的公司,也是一只著名的蓝筹股,当宝丽来公司的销售和盈利都大幅度下滑时(我们前面对这种情况已经进行讨论),许多投资者根本没有注意到股价实际上已经严重高估了,相反他们不停地用一些自欺欺人的说法来安慰自己:“股价已经下跌这么多了,不可能再跌了,”或者“好公司的股票总是会涨回来了”“在股市投资上必须要有耐心”以及“由于恐慌而卖出一只好股票是愚蠢的”.

12个愚蠢的 Windows 默认设置你一定要改的

- - 开源中国社区最新新闻
如果你购买了一辆新车,肯定会调整座椅、调整收音机音量,将一切调整到最舒适的状态. 同理,Windows PC也是一样,大部分的默认设置可能都不够人性化,如果你无法忍受,不如参考一下下面的12个小技巧,将这些愚蠢的默认设置替换掉:. 1.退格键在浏览器中的返回功能. 首先,在默认情况下,使用网页浏览器时按下退格键会返回到上一个页面,常常会因为输入焦点切换退格误操作而丢失正在进行的工作,令人十分烦恼.

愚蠢的人类啊!在AI的极限微操下颤抖吧![v]

- YiLeuang - 煎蛋
这两个视频是由名叫“Automaton 2000”的微操bot演示的微操极限. 第一个视频: 20机枪兵,对战40自爆虫. 机枪兵们啃兴奋剂且战且退,将游击战发挥到极致,无一死亡全歼自爆虫;. 第二个视频: 100小狗,对战20辆架了炮的坦克. 如果一堆狗冲过去的话只能干爆两辆坦克,该怎样微操呢. Read the rest of 愚蠢的人类啊.