天天看點

C語言中史上最愚蠢的Bug

1

2

3

4

else if (code == 200) {     // Downloading whole file

    /* Write new file (plus allow reading once we finish) */

    g = fname ? fopen(fname, "w+") : tmpfile();

}

于是作者就先把這個問題記下來,在注釋中寫下了FIXME:

5

6

7

    // FIXME Win32 native version fails here because

    //   Microsoft's version of tmpfile() creates the file in C:\

然後,作者覺得需要寫一個跨平台的編譯:

FILE * tmpfile ( void ) {

#ifndef _WIN32

    return tmpfile();

#else

    //code for Windows;

#endif

然後,作者覺得這樣實作很不好,會發現名字沖突,因為這樣一來這個函數太難看了。于是他重構了一下他的代碼——寫一個自己實作的tmpfile() – w32_tmpfile,然後,在Windows 下用宏定義來重命名這個函數為tmpfile()。(陳皓注:這種用法是比較标準的跨平台代碼的寫法)

#ifdef _WIN32

  #define tmpfile w32_tmpfile

FILE * w32_tmpfile ( void ) {

搞定!編譯程式,運作。靠!居然沒有調用到我的w32_tmpfile(),什麼問題?調試,單步跟蹤,果然沒有調用到!難道是問号表達式有問題?改成if – else 語句,好了!

if(NULL != fname) {

    g = fopen(fname, "w+");

} else {

    g = tmpfile();

問号表達式不應該有問題吧,難道我們的宏對問号表達式不起作用,這難道是編譯器的預編譯的一個bug?作者懷疑到。

現在我們把所有的代碼連在一起看,并比較一下:

能正常工作的代碼

8

9

10

11

12

13

14

15

16

17

18

19

#  define tmpfile w32_tmpfile

    code for Windows;

    //     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();

    }

不能正常工作的代碼

    //    Microsoft's version of tmpfile() creates the file in C:\

也許你在一開始就看到了這個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能工作的原因是因為作者注釋了老的問号表達式的代碼,是以,那段能工作的代碼成了:

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

我相信,當作者找到這個問題的原因後,一定會罵一句“媽的”!我也相信,這個bug花費了作者很多時間!

最後,我也share一個我以前犯的一個錯。

我有一個小函數,需要傳入一個int* pInt的類型,然後我需要在我的代碼裡 把這個int* pInt作除數。于是我的代碼成了下面的這個樣子:

float result = num/*pInt; …. /*  some comments */ -x

因為我在我當時用vi編寫代碼,是以沒有文法高亮,而我的程式都編譯通過了,但是卻出現了很奇怪的事。我也不知道,用gdb調式的時候,發現有些語句直接就過了。這個問題讓我花了很多時間,最後發現問題原來是沒有空格導緻的,TNND,下面我用代碼高亮的插件來顯示上面的代碼,

....

Holly Shit!  我的代碼成了:

float result = num-x

媽的!我的這個錯誤在愚蠢程度上和上面那個作者出的錯誤有一拼。

(全文完)

<a href="http://coolshell.cn/articles/5388.html" target="_blank">http://coolshell.cn/articles/5388.html</a>

繼續閱讀