Why is strtok() Considered Unsafe?
我需要注意的
对我来说有点奇怪的是,在VisualC++中,EDCOX1 1(它是"安全的")有一个额外的"上下文"参数,但是看起来它在其他方面是相同的。是相同的,还是实际上不同?
根据本文件的strtok_节:
6.7.3.1 The strtok_s function The strtok_s function fixes two problems
in the strtok function:A new parameter, s1max, prevents strtok_s from storing outside of the
string being tokenized. (The string
being divided into tokens is both an
input and output of the function since
strtok_s stores null characters into
the string.)A new parameter, ptr, eliminates the static internal state that
prevents strtok from being re-entrant
(Subclause 1.1.12). (The ISO/IEC 9899
function wcstok and the ISO/IEC 9945
(POSIX) function strtok_r fix this
problem identically.)
没有什么不安全的。你只需要了解它是如何工作的以及如何使用它。在编写代码和单元测试之后,用valgrind重新运行单元测试只需要几分钟的额外时间,以确保在内存边界内运行。手册上说的都是:
BUGS
Be cautious when using these functions. If you do use them, note that:
- These functions modify their first argument.
- These functions cannot be used on constant strings.
- The identity of the delimiting character is lost.
- The
strtok() function uses a static buffer while parsing, so it's not thread safe. Usestrtok_r() if this matters to you.
Stutk在VisualC++中是安全的(但在其他地方),因为它使用线程本地存储来保存调用之间的状态。在其他地方,全局变量用于保存strtok()状态。
然而,即使在VC++中,strtok是线程安全的,它仍然有点奇怪——不能同时在同一线程中的不同字符串上使用strtok()。例如,这不会很好地工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
它不能很好地工作的原因-对于每个线程,只有一个状态可以保存在线程本地存储中,在这里,第一个字符串和第二个字符串需要两个状态。因此,虽然strtok使用vc++是线程安全的,但它是不可重入的。
strtok-s(或其他任何地方的strtok-r)所提供的——一个明确的状态,然后strtok就变成可重入状态。
如果没有正确的以空结尾的字符串,则会导致缓冲区溢出。还要注意(这是我学到的最难的方法)strtok似乎并不关心内部字符串。例如,"hello"/"world"将解析"hello"/"world",而"hello/world"将解析为"hello world"。注意,它在/上拆分,忽略了它在圆括号内的事实。