strtok
的哪些功能是不安全的(就缓冲区溢出而言)需要注意哪些?
对我来说有点奇怪的是,Visual C ++中的strtok_s
(这是“安全的”)有一个额外的“上下文”参数,但看起来它在其他方面是相同的...是它相同,还是实际上不一样?
答案 0 :(得分:24)
根据this document的strtok_s部分:
6.7.3.1 strtok_s函数strtok_s函数修复了两个问题 在strtok函数中:
- 新参数s1max阻止strtok_s存储在 字符串被标记化。 (字符串 分为代币是一种 输入和输出函数,因为 strtok_s将空字符存储到 字符串。)
- 新参数ptr消除了静态内部状态 防止strtok重入 (第1.1.12条)。 (ISO / IEC 9899 功能wcstok和ISO / IEC 9945 (POSIX)函数strtok_r解决了这个问题 问题完全相同。)
醇>
答案 1 :(得分:12)
没有什么不安全的。您只需要了解它是如何工作的以及如何使用它。在编写代码和单元测试之后,只需花费几分钟的时间就可以使用valgrind重新运行单元测试,以确保使用内存限制。手册页说明了一切:
<强> BUGS 强>
使用这些功能时要小心。如果您确实使用它们,请注意:
- 这些函数修改了他们的第一个参数。
- 这些函数不能用于常量字符串。
- 分隔字符的标识丢失。
strtok()
函数在解析时使用静态缓冲区,因此它不是线程安全的。如果这对您很重要,请使用strtok_r()
。
答案 2 :(得分:5)
strtok在Visual C ++中是安全的(但不是其他地方),因为它使用线程本地存储来在调用之间保存其状态。在其他地方,全局变量用于保存strtok()状态。
然而即使在VC ++中,strtok是线程安全的,它仍然有点奇怪 - 你不能同时在同一个线程中的不同字符串上使用strtok()。例如,这不会很好:
token = strtok( string, seps );
while(token)
{
printf("token=%s\n", token)
token2 = strtok(string2, seps);
while(token2)
{
printf("token2=%s", token2);
token2 = strtok( NULL, seps );
}
token = strtok( NULL, seps );
}
它不能很好地工作的原因 - 每个线程只有单个状态可以保存在线程本地存储中,这里需要2个状态 - 第一个字符串和第二个字符串。因此,虽然strtok对VC ++是线程安全的,但它不是可重入的。
strtok_s(或其他地方的strtok_r)提供了什么 - 一个明确的状态,并且strtok变为可重入。
答案 3 :(得分:0)
如果没有正确的空终止字符串;你将最终陷入缓冲区溢出。还要注意(这是我学到的东西)strtok似乎并不关心内部字符串。 I.E.拥有“hello”/“world”将解析“hello”/“world”,而“hello / world”将解析为“hello world”。请注意,它会拆分/并忽略它在括号内的事实。