首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言史上最愚蠢的 Bug:註釋裡的反斜杠吞了代碼

     編輯:關於C語言

事故現場:跨平台 tmpfile 失效

作者編寫 HTTP 下載工具,需跨平台創建臨時文件。Unix 下 tmpfile() 正常,Windows 下卻在 C:\ 創建文件(需管理員權限),導致失敗。於是寫了跨平台封裝:

#ifdef _WIN32
#define tmpfile w32_tmpfile
#endif

FILE* w32_tmpfile(void) { /* Windows 實現 */ }

調用處使用三元運算符:

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

編譯通過,運行卻**不調用** w32_tmpfile。改用 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();

註釋最後一行 C:\ 結尾的反斜杠 \ 在 C/C++ 中代表「行繼續」,導致下一行代碼也被視為註釋一部分!

為何 if-else 版本能工作?

因為作者在修改時**註釋掉了**原三元運算符那行:

// FIXME ... C:\
//g = fname ? fopen(fname, "w+") : tmpfile();  ← 這行被吞了沒關係
if (NULL != fname) { ... }  ← 新代碼在註釋外,正常編譯

作者的另一個「經典」錯誤

float result = num/*pInt;
...
/* some comments */
num++;

意圖寫 num / *pInt,但漏了空格導致 /* 開啟註釋,一直持續到 */,中間代碼全「消失」。

深層教訓與防範

  1. 註釋裡別寫反斜杠結尾的路徑,或用 C:/、C:\\、原始字符串 R"(C:\)"。
  2. 啟用編譯器警告:GCC -Wcomment、MSVC /W4 會提示「註釋中的反斜杠新行」。
  3. 使用語法高亮編輯器/IDE,註釋顏色會立即暴露代碼被吞噬。
  4. 三元運算符換行時加括號:g = fname ? fopen(...) : (tmpfile()); 縱使被吞也只影響該表達式,不影響後續邏輯(但仍會編譯錯誤)。

結語

這個 Bug 堪稱「愚蠢」是因為它**極其隱蔽、極其低級、極其浪費時間**。每個 C/C++ 程序員都應在職業生涯早期栽一次這個跟頭,然後永遠記住:**註釋也是代碼的一部分,請像對待代碼一樣審視它們。**

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved