[英]strtok_s and compilers C11 onward compliance
C11 中strtok_s
的聲明及其用法看起來與編譯器中的strtok_s
非常不同,例如與 Visual Studio 2022 (17.4.4) 捆綁在一起的最新版本以及 GCC 12.2.0(查看 MinGW64 發行版)。
我擔心這種不同的形式早在 C11 之前就已被開發為strtok
的更安全且被接受的替代品。 如果有人想使用strtok_s
並保持 C11 兼容,現在會發生什么?
編譯器提供的庫是否符合 C11 標准?
也許只是我被一些明顯的事情所愚弄,有人可以幫助我......
這是 C11(類似於 C17 和 C23 的早期草稿):
char *strtok_s(char * restrict s1,
rsize_t * restrict s1max,
const char * restrict s2,
char ** restrict ptr);
同樣可以在safec 庫中找到很好的參考
雖然MSC/VC和 GCC 具有以下形式
char* strtok_s(
char* str,
const char* delimiters,
char** context
);
C11“附件 K 邊界檢查接口”受到了很多質疑,實際上幾乎沒有標准庫實現它。 請參閱附件 K 的現場經驗示例 - 邊界檢查接口。
至於 MSVC 編譯器,它不符合任何 C 標准,也從未做出這樣的聲明 - 你可以試試這個來檢查你是否使用這樣的編譯器:
#if !defined(__STDC__) || (__STDC__==0)
#error This compiler is non-conforming.
#endif
特別是,MSVC 也沒有實現 Annex K,但在 C11 之前已經有了非標准庫擴展。
在實踐中_s
意味着:
如果可移植性和標准一致性很重要,那么請避免使用_s
函數。
在實踐中, _s
函數可以防止兩件事:傳遞未凈化的輸入或 null 指針。 因此,假設您進行了適當的輸入清理並且沒有將 null 指針傳遞給庫函數,那么_s
函數不會給您額外的安全性,只會帶來額外的執行膨脹和可移植性問題。
如果有人想使用
strtok_s
並保持 C11 兼容,現在會發生什么?
你事實上不能。
而且它不僅限於strtok_s()
。 整個 C11 Annex K 實現集是支離破碎的,因為與標准的主要偏差來自 Microsoft 的實現,可能永遠沒有辦法使用 Annex K 函數編寫可移植的、符合標准的代碼。
可用的實現
盡管 API 的規范已經存在了十多年,但只有少數實現具有不同程度的完整性和一致性。 以下是對已知存在的實施及其狀態的調查。
雖然下面的兩個實現以可移植源代碼形式作為開源項目提供,但沒有一個流行的開源發行版(如 BSD 或 Linux)選擇將其中一個提供給他們的用戶。 至少有一個(GNU C 庫)一再拒絕包含的提議,原因與奧斯汀集團在他們對 TR 24731-1 N1106 的初步審查中指出的一些相同的原因。 這些發行版的未來版本似乎不太可能提供這些 API。
微軟視覺工作室
Microsoft Visual Studio 實現了早期版本的 API。 但是,該實現並不完整,既不符合 C11 也不符合原始 TR 24731-1。 例如,它不提供
set_constraint_handler_s
function 而是定義一個_invalid_parameter_handler _set_invalid_parameter_handler(_invalid_parameter_handler)
function 具有類似的行為,但簽名略有不同且不兼容。 它還沒有定義abort_handler_s
和ignore_handler_s
函數、memset_s
function(它不是 TR 的一部分)或RSIZE_MAX
宏。 Microsoft 實現也不將重疊的源序列和目標序列視為運行時約束違規,而是在這種情況下具有未定義的行為。由於與規范存在大量偏差,Microsoft 實施不能被視為符合規范或可移植。
...
保險箱 C 圖書館
Safe C 庫 [SafeC] 是一個相當高效和可移植但不幸的是非常不完整的 Annex K 實現,它支持
<string.h>
中聲明的函數的字符串操作子集。由於它不支持
<string.h>
函數之外的 Annex K 設施,安全 C 庫不能被視為符合要求的實現。
甚至 Safe C 庫也不符合要求。
這些功能是否“更安全”值得商榷。 閱讀整個文檔。
不必要的使用
微軟為了提高 API 的采用率而棄用標准函數而產生的一個普遍謬論是,對標准函數的每次調用都必然是不安全的,應該用“更安全”的 API 來代替。因此,安全有思想的團隊有時會天真地開始長達數月的項目,重寫他們的工作代碼,並盡職盡責地用相應的 API 替換所有“已棄用”函數的實例。 這不僅會導致不必要的改動並增加將新錯誤注入正確代碼的風險,還會降低重寫代碼的效率。
此外,請閱讀更新后的N1969 更新現場經驗與附件 K — 邊界檢查接口:
盡管自最初提議以來已有十多年,自 ISO/IEC TR 24731-1:2007 獲得批准已近十年,自將邊界檢查接口引入 C 標准已近五年,但仍未出現可行的合規實現. API 繼續存在爭議,實施請求繼續被實施者拒絕。
邊界檢查接口的設計雖然用心良苦,但存在太多問題需要糾正。 與依賴既定方法或現代技術相比,使用 API 已被認為會導致質量更差、安全性更低的軟件。 更有效和侵入性更小的方法已變得司空見慣,並且通常受到用戶和安全專家的青睞。
因此,我們建議將 Annex K 從 C 標准的下一次修訂中刪除,或者棄用后再刪除。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.