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 library中可以找到相同的良好参考
而MSC/VC和GCC的格式为
char* strtok_s(
char* str,
const char* delimiters,
char** context
);
2条答案
按热度按时间f5emj3cl1#
C11“Annex K bounds checking interfaces”受到了很多质疑,实际上几乎没有标准库实现它,例如Field Experience With Annex K — Bounds Checking Interfaces。
至于MSVC编译器,它不符合任何C标准,也从未做过这样的声明--你可以试试这个来检查你是否在使用这样的编译器:
特别是,MSVC也没有实现附录K,但是在C11之前已经有了非标准的库扩展。
实际上,
_s
表示:如果可移植性和标准一致性很重要,那么就避免使用
_s
函数。在实践中,
_s
函数可以防止两种情况:所以假设你做了正确的输入清理并且没有给库函数传递空指针,_s
函数并没有给你额外的安全性,只是额外的执行膨胀和可移植性问题。ecbunoof2#
如果有人想使用
strtok_s
并保持C11兼容性,现在会发生什么?你 * 事实上*不能。
它不仅限于
strtok_s()
,整个C11附录K的实现集都是分裂的,因为与标准的主要偏差来自微软的实现,可能永远不会有一种方法来编写可移植的,符合标准的代码使用附录K的函数。根据N1967附录K现场经验-边界检查界面:
可用的实现
尽管API的规范已经存在了十多年,但只有少数实现具有不同程度的完整性和一致性。以下是已知存在的实现及其状态的调查。
虽然下面的两个实现可以作为开源项目以可移植源代码的形式提供,没有一个流行的开源发行版,如BSD或Linux,选择让它们的用户可以使用其中的任何一个。(GNU C Library)曾多次拒绝包含的建议,其原因与Austin小组在其对TR 24731-1 N1106的初步审查中所指出的相同]。这些发行版的未来版本似乎不太可能提供这些API。
微软可视化工作室
Microsoft Visual Studio实现了API的早期版本。但是,该实现不完整,既不符合C11,也不符合原始TR 24731-1。例如,它不提供
set_constraint_handler_s
函数,而是定义了一个_invalid_parameter_handler _set_invalid_parameter_handler(_invalid_parameter_handler)
函数,该函数具有类似的行为,但签名略有不同且不兼容。不要定义abort_handler_s
和ignore_handler_s
函数、memset_s
函数(不是TR的一部分)或RSIZE_MAX
宏。Microsoft实现也不会将重叠的源序列和目标序列视为运行时约束冲突,而是在此类情况下具有未定义的行为。由于与规范存在大量偏差,因此Microsoft实现不能被视为符合规范或可移植。
...
安全C库
Safe C Library [SafeC]是一个相当高效和可移植的附件K的实现,但不幸的是它非常不完整,支持
<string.h>
中声明的字符串操作函数子集。由于缺乏对
<string.h>
函数以外的附录K设施的支持,因此不能将Safe C库视为符合标准的实现。即使是安全C库也是不一致的。
这些功能是否“更安全”是有争议的。阅读整个文档。
不必要的使用
微软为了提高API的采用率而弃用标准函数,由此产生了一个普遍的谬误,即对标准函数的每次调用都必然是不安全的,应该被对“更安全”API的调用所取代。有安全意识的团队有时会天真地开始长达数月的项目,重写他们的工作代码并尽职尽责地替换所有“已弃用”的示例这不仅会导致不必要的混乱,增加在正确代码中注入新错误的风险,还会降低重写代码的效率。
另外,请阅读更新的N1969 Updated Field Experience With Annex K — Bounds Checking Interfaces:
尽管最初的提议已经提出了十多年,ISO/IEC TR 24731-1:2007已经批准了近十年,边界检查接口引入C标准也已经有近五年了,还没有出现可行的符合标准的实现。API仍然存在争议,实现请求仍然被实现者拒绝。
边界检查接口的设计虽然初衷良好,但存在太多问题需要纠正。与依赖现有方法或现代技术相比,使用API会导致软件质量下降、安全性降低。更有效、侵入性更低的方法已变得普遍,通常受到用户和安全Maven的青睐。
因此,我们建议从C标准的下一个修订版中删除附录K,或者先弃用再删除。