標籤:

clang-format 格式宏代碼引起的 Bug

今天同事遇到一個 clang-format 格式代碼引起的 bug,問我 clang-format 有沒有選項來避免這個問題。這個 bug 挺有趣的,記錄一下。

格式之前,原來代碼類似這樣:

#import <Foundation/Foundation.h>#define DB_TableName(n) @"tb_"#nint main(int argc, const char *argv[]) { @autoreleasepool { long long uid = 12334; NSString *table = [NSString stringWithFormat:DB_TableName(FriendMessage_%lld), uid]; NSLog(@"%@", table); } return 0;}

其中 DB_TableName 是一個宏,在字元串前面沾上 tb_ 前綴。這樣 DB_TableName(FriendMessage_%lld) 展開後為 @"tb_FriendMessage_%lld"。代碼執行後 table 的值為 @"tb_FriendMessage_12334"。

但 clang-format 從語法本身,區分不了 DB_TableName(FriendMessage_%lld) 應該進行宏展開,而認為它是一個函數調用,傳入表達式 FriendMessage_%lld 作為參數。這個表達式是取余,% 是二元符號,就在 % 前後添加了一個空格。於是格式後的代碼變成:

#import <Foundation/Foundation.h>#define DB_TableName(n) @"tb_" #nint main(int argc, const char *argv[]) { @autoreleasepool { long long uid = 12334; NSString *table = [NSString stringWithFormat:DB_TableName(FriendMessage_ % lld), uid]; NSLog(@"%@", table); } return 0;}

DB_TableName(FriendMessage_ % lld) 展開後為 @"tb_FriendMessage_ % lld",執行代碼後 table 值為 @"tb_FriendMessage_ 12334"。

接下來的操作是使用 table 的值去訪問 sqlite 資料庫,就引起了錯誤。

這個 bug 似乎是 clang-format 的問題,但實質是宏定義惹的禍。這個宏很危險的,是個地雷,只是現在剛好踩到,就炸開了。最後我沒有找到 clang-format 選項可以避免這種問題,只能注意能夠不寫宏就不寫宏。

推薦閱讀:

【實驗】Adversarial Video Generation
AI 代碼長啥樣?
你若眼熟,真的純屬巧合。

TAG:代碼 |