ISO C委员会(ISO/IEC JTC1/SC21/WG14)已发布TR 24731-1,正在研究TR 24731-2:
TR 24731-1:C库的扩展第一部分:边界检查接口
WG14正在研究更安全的C库函数.该TR旨在通过添加具有缓冲区长度的额外参数来修改现有程序.最新草案见N1225号文件.理由是在N1173号文件中.这将成为技术报告类型2.
TR 24731-2:C库的扩展 - 第二部分:动态分配功能
WG14正在研究更安全的C库函数.该TR面向使用动态分配而不是缓冲区长度的额外参数的新程序.最新草案见N1337号文件.这将成为技术报告类型2.
您是否使用支持TR24731-1功能的库或编译器?
如果是这样,哪个编译器或库以及哪个平台?
您是否因修复代码以使用这些功能而发现任何错误?
哪些功能提供最大价值?
有没有提供任何价值或负值?
你打算将来使用这个图书馆吗?
您是否正在跟踪TR24731-2的工作?
Robert Gambl.. 65
自从它们诞生之初(当它是一个TR)时,我一直是这些TR的声音批评者,并且永远不会在我的任何软件中使用它们.它们掩盖症状而不是解决原因,我认为,如果有的话,它们会对软件设计产生负面影响,因为它们提供了错误的安全感,而不是促进可以更有效地实现相同目标的现有实践.我并不孤单,事实上我并不知道在委员会之外开发这些TR的一个主要支持者.
我使用glibc并因此知道我将不得不处理这些废话,因为glibc的主要维护者Ulrich Drepper 谈到了这个主题:
建议的安全(r)ISO C库无法完全解决问题.......提议让程序员的生活更加艰难并不会有所帮助.但这正是提出的建议.......他们都需要做更多的工作或者只是愚蠢的.
他接着详细介绍了一些拟议函数的问题,并在其他地方表示glibc永远不会支持这一点.
奥斯汀集团(负责维护POSIX)对TR提供了非常严格的审查,他们的评论和委员会的回复在这里提供.奥斯汀集团的审查工作非常好,详细说明了TR的许多问题,所以我不会在这里详细介绍个别细节.
所以底线是:我没有使用支持或支持这个的实现,我不打算永远使用这些功能,我看不到TR中的正面价值.我个人认为,TR仍然以任何形式存在的唯一原因是因为它受到了微软的推动,最近证明尽管标准委员会仍有广泛的反对意见,但它已经证明能够让事情陷入困境.如果这些功能被标准化,我认为它们不会被广泛使用,因为该提案已经存在了几年,并且未能获得任何真正的社区支持.
自从它们诞生之初(当它是一个TR)时,我一直是这些TR的声音批评者,并且永远不会在我的任何软件中使用它们.它们掩盖症状而不是解决原因,我认为,如果有的话,它们会对软件设计产生负面影响,因为它们提供了错误的安全感,而不是促进可以更有效地实现相同目标的现有实践.我并不孤单,事实上我并不知道在委员会之外开发这些TR的一个主要支持者.
我使用glibc并因此知道我将不得不处理这些废话,因为glibc的主要维护者Ulrich Drepper 谈到了这个主题:
建议的安全(r)ISO C库无法完全解决问题.......提议让程序员的生活更加艰难并不会有所帮助.但这正是提出的建议.......他们都需要做更多的工作或者只是愚蠢的.
他接着详细介绍了一些拟议函数的问题,并在其他地方表示glibc永远不会支持这一点.
奥斯汀集团(负责维护POSIX)对TR提供了非常严格的审查,他们的评论和委员会的回复在这里提供.奥斯汀集团的审查工作非常好,详细说明了TR的许多问题,所以我不会在这里详细介绍个别细节.
所以底线是:我没有使用支持或支持这个的实现,我不打算永远使用这些功能,我看不到TR中的正面价值.我个人认为,TR仍然以任何形式存在的唯一原因是因为它受到了微软的推动,最近证明尽管标准委员会仍有广泛的反对意见,但它已经证明能够让事情陷入困境.如果这些功能被标准化,我认为它们不会被广泛使用,因为该提案已经存在了几年,并且未能获得任何真正的社区支持.
我喜欢罗伯特的答案,但我也对我提出的问题有一些看法.
您是否使用支持TR24731-1功能的库或编译器?
不,我没有.
如果是这样,哪个编译器或库以及哪个平台?
我相信这些功能是由MS Visual Studio(例如MS VC++ 2008 Edition)提供的,并且有警告鼓励您使用它们.
您是否因修复代码以使用这些功能而发现任何错误?
还没.而且我不希望在我的代码中发现许多内容.我使用的其他一些代码 - 也许吧.但我还没有被说服.
哪些功能提供最大价值?
我喜欢printf_s()系列函数不接受'
%n
'格式说明符的事实.
有没有提供任何价值或负值?
这些
tmpfile_s()
和tmpnam_s()
功能令人非常失望.他们真的需要工作更像mkstemp()
是创建文件并打开它以确保没有TOCTOU(检查时间,使用时间)漏洞.就目前而言,这两者提供的价值非常小.我也认为这
strerrorlen_s()
提供的价值非常小.
你打算将来使用这个图书馆吗?
我有两种想法.我开始研究一个库,该库可以在标准C库上实现TR 24731的功能,但是由于证明它正常工作所需的单元测试数量而被抓住了.我不确定是否继续这样做.我有一些代码,我想移植到Windows(主要是出于在所有平台上提供支持的反常愿望 - 它已经在Unix衍生品上工作了几十年).不幸的是,为了让它在没有来自MSVC编译器的警告的情况下进行编译,我必须使用完全可靠(当仔细使用时)标准C库函数来防止MSVC对我产生干扰.这并不开胃.很糟糕的是,我必须处理在这段时间内发展起来的大部分二十年的系统; 不得不处理某人的乐趣想法(让人们在不需要时采用TR 24731)很烦人.这就是我开始进行库开发的原因 - 允许我在Unix和Windows上使用相同的接口.但我不确定我会从这里做些什么.
您是否正在跟踪TR24731-2的工作?
在收集问题数据之前我去标准网站之前我没有跟踪它.这些
asprintf()
和vasprintf()
功能可能很有价值; 我会用那些.我不确定内存流I/O功能.在strdup()
C级标准化将是向前迈出的一大步.对于我来说,这似乎比第1部分(边界检查)接口更少争议.
总的来说,我不相信第1部分"Bounds-Checking Interfaces".第2部分"动态分配函数"草案中的材料更好.
如果由我决定,我会稍微沿着第1部分的方向移动,但我还修改了C99标准C库中的接口,它返回char *
到字符串的开头(例如strcpy()
和strcat()
),而不是返回指向开头的指针,它们将返回指向新字符串末尾的空字节的指针.这会使一些常见的习语(例如重复地将字符串连接到另一个字符串的末尾)更有效,因为它会使得避免重复使用的代码所呈现的二次行为变得微不足道strcat()
.替换将确保输出字符串的空终止,如TR24731版本.我并不完全反对检查接口的概念,也不反对异常处理函数.这是一项棘手的业务.
更新(2011-05-08)
另见这个问题.遗憾的是,对于TR24731函数的有用性而言,有些函数的定义在Microsoft实现和标准之间有所不同,使得它们对我来说毫无用处.我的答案引用了vsnprintf_s()
.
例如,TR 24731-1表示接口
vsnprintf_s()
是:#define __STDC_WANT_LIB_EXT1__ 1 #include#include int vsnprintf_s(char * restrict s, rsize_t n, const char * restrict format, va_list arg); 不幸的是,MSDN说接口
vsnprintf_s()
是:int vsnprintf_s( char *buffer, size_t sizeOfBuffer, size_t count, const char *format, va_list argptr );参数
buffer - 输出的存储位置.
sizeOfBuffer - 输出缓冲区的大小.
count - 要写入的最大字符数(不包括终止空值)或_TRUNCATE.
格式 - 格式规范.
argptr - 指向参数列表的指针.
请注意,这不仅仅是类型映射的问题:固定参数的数量是不同的,因此是不可调和的.我也不清楚(也可能是标准委员会)对'sizeOfBuffer'和'count'都有什么好处; 它看起来像两次相同的信息(或者,至少,代码通常用两个参数的相同值写入).
同样,也存在问题scanf_s()
及其亲属. Microsoft表示缓冲区长度参数的类型是unsigned
(明确说明'size参数是类型unsigned
,而不是size_t
').相反,在附件K中,size参数是类型rsize_t
,它是size_t
(rsize_t
的另一个名称size_t
,但是RSIZE_MAX
小于SIZE_MAX
)的限制变体.因此,scanf_s()
对于Microsoft C和Standard C ,代码调用必须以不同方式编写.
最初,我计划使用'安全'函数来获取一些代码,以便在Windows和Unix上干净地编译,而无需编写条件代码.由于微软和ISO功能并不总是相同,因此失败了,现在是时候放弃了.
vsnprintf()
Visual Studio 2015 中Microsoft的变化在Visual Studio 2015文档中vsnprintf()
,它指出界面已更改:
从Visual Studio 2015和Windows 10中的UCRT开始,
vsnprintf
不再完全相同_vsnprintf
.该vsnprintf
功能符合C99标准;_vnsprintf
保留以实现向后兼容性.
但是,Microsoft的界面vsnprintf_s()
并没有改变.
C11标准变体localtime_s()
在ISO/IEC 9899:2011附录K.3.8.2.4中定义为:
struct tm *localtime_s(const time_t * restrict timer, struct tm * restrict result);
与localtime_s()
定义为的MSDN变体相比:
errno_t localtime_s(struct tm* _tm, const time_t *time);
和POSIX变体localtime_r()
定义为:
struct tm *localtime_r(const time_t *restrict timer, struct tm *restrict result);
C11标准和POSIX功能与名称不同.Microsoft功能在界面上有所不同,即使它与C11标准共享一个名称.
差异另一个例子是微软的strtok_s()
和附录K的strtok_s()
:
char *strtok_s(char *strToken, const char *strDelimit, char **context);
VS:
char *strtok_s(char * restrict s1, rsize_t * restrict s1max, const char * restrict s2, char ** restrict ptr);
请注意,Microsoft变体有3个参数,而附件K变量有4个.这意味着Microsoft的参数列表strtok_s()
与POSIX兼容strtok_r()
- 因此,如果更改函数名称(例如通过宏),对这些参数的调用可以有效地互换 - 但是标准C(附件K)版本与额外参数不同.
问题Mac和Linux上的不同声明qsort_r()
有一个答案,也是qsort_s()
由Microsoft qsort_s()
定义并由TR24731-1定义 - 再次,接口是不同的.
C11标准(2010年12月草案 ;您可以从ANSI网上商店获得30美元的最终标准,ISO/IEC 9899:2011的PDF副本)确实具有TR24731-1作为其中的可选部分标准.它们在附录K(边界检查接口)中定义,它是"规范的"而不是"信息性的",但它是可选的.
C11标准中没有TR24731-2功能 - 这很难过,因为vasprintf()
功能及其相关功能可能非常有用.
快速摘要:
C11含有TR24731-1
C11不含TR24731-2
Deduplicator在对另一个问题的评论中指出,在ISO C标准委员会(ISO/IEC JTC1/SC22/WG14)之前有一个提案
附件K的 N1967 现场经验 - 界限检查接口
它包含对附件K函数的一些现有实现的引用 - 它们都没有广泛使用(但如果您感兴趣,可以通过文档找到它们).
该文件以建议结束:
因此,我们建议将附件K从C标准的下一版本中删除,或者弃用然后删除.
我支持这个建议.
好了,现在一台用于 TR24731-2:
是的,我已经使用过asprintf()
/ vasprintf()
自从我在glibc中看到它们之后,是的,我是他们的坚强拥护者.
为什么?因为它们能够一次又一次地提供我需要的功能:一种功能强大,灵活,安全且(相对)易于使用的方式,可将任何文本格式化为新分配的字符串.
我也非常赞成memstreams:喜欢memstream
,asprintf()
(不是open_memstream()
!!!)为你分配一个足够大的缓冲区并让你进行fmemopen()
打印,所以你的打印功能完全不知道它们是否打印成字符串或者文件,你可以简单地忘记问题,你需要多少空间.
您是否使用支持TR24731-1功能的库或编译器?如果是这样,哪个编译器或库以及哪个平台?
是的,Visual Studio 2005和2008(显然是针对Win32开发).
您是否因修复代码以使用这些功能而发现任何错误?
....我编写了自己的安全功能库(我们经常使用的只有15个),可以在多个平台上使用 - Linux,Windows,VxWorks,INtime,RTX和uItron.创建安全功能的原因是:
由于不正确使用标准C函数,我们遇到了大量错误.
我对TR函数传递或返回的信息不满意,或者在某些情况下,他们的POSIX替代品.
编写函数后,发现了更多错误.所以,是的,使用这些功能是有价值的.
哪些功能提供最大价值?
更安全的vsnprintf,strncpy,strncat版本.
有没有提供任何价值或负值?
fopen_s和类似的功能对我个人来说几乎没有什么价值.如果fopen返回NULL,我很好.您应该始终检查函数的返回值.如果有人忽略了fopen的返回值,那么是什么让他们检查fopen_s的返回值?我知道fopen_s将返回更具体的错误信息,这些信息在某些情况下很有用.但是对于我正在做的事情,这并不重要.
你打算将来使用这个图书馆吗?
我们现在正在使用它 - 在我们自己的"安全"库中.
您是否正在跟踪TR24731-2的工作?
没有.
不,这些功能绝对无用,除了鼓励编写代码以外它没有任何用途,所以它只能在Windows上编译.
snprintf非常安全(正确实现时),因此snprintf_s毫无意义.如果缓冲区溢出(通过清除连接到字符串),strcat_s将销毁数据.还有许多其他完全无知事情如何运作的例子.
真正有用的功能是BSD strlcpy和strlcat.但微软和Drepper都因为自己的私利原因拒绝了这些,以及各地C程序员的烦恼.