gpt4 book ai didi

c - 显式使用 strtok 是否足以使其可重入?

转载 作者:行者123 更新时间:2023-12-03 23:55:49 25 4
gpt4 key购买 nike

引用 C11(N1570 草案),7.24.5.8 strtok 函数:

The strtok function is not required to avoid data races with other calls to the strtok function.311)

311) The strtok_s function can be used instead to avoid data races.



据我了解,这是由于它的(全局)内部状态,它保留有关下一个 token 当前位置的信息。这允许像以下习语一样使用它:
p = strtok(str, delim);
while (p != NULL)
{
puts(p);
p = strtok(NULL, delim);
}

假设 strtok_s (在附件 K 中定义)不可用,以下用法是否足以重入,因为它完全忽略了内部状态?
char str[] = "ab;cd";
char * const endstr = str + strlen(str);
const char *delim = ";";

char *p = strtok(str, delim);
while (p != NULL)
{
puts(p);

if (p + strlen(p) == endstr) // detect ending token
break;
p = strtok(p + strlen(p)+1, delim);
}

更新:

再想一想,这种技术可能永远不应该使用,因为它可能会导致安全问题。由于最后一次调用 NULL 时序列永远不会结束。 , strtok的内部状态(由地址到 token 字符串组成)可以在应用程序的剩余生命周期中保留。

最佳答案

would the following usage be sufficient for reentrancy, since it ignores the internal state entirely? [...]



你怎么知道你的替代方案是否忽略了 strtok()的内部状态完全?该州的性质和用途的具体细节尚未明确。因此,在不引用特定实现的情况下,我们只知道在再次使用 NULL 调用该函数时跟踪下一个标记的开始就足够了。作为它的第一个论点。没有什么比这更值得依赖的了。

现在,我承认似乎静态状态应该仅由单个 char * 组成。 ,并且该函数在传递非空第一个参数时的行为不应依赖于该静态状态的值。我想这就是你所说的“可重入”。但是,我不会使用该术语,因为尽管您的方法可能会产生不受其他线程操作影响的结果,但它仍然会影响(并与其他线程进行数据竞争)不遵循相同模式的其他线程.

最后,是的,确实存在涉及 strtok() 的数据竞争的可能性。 .如果两个不同的线程调用 strtok()并且至少通过一次 NULL作为第一个参数,然后两个线程都修改该函数的静态状态,并且至少有一个读取它。 strtok()不需要以任何特定方式保护其内部状态,因此如果调用未以某种方式在外部同步,则可能存在数据竞争。在这种情况下,程序行为未定义。

因此,如果您有理由担心与 strtok() 相关的不可重入性和数据竞争风险。 ,而您不想依赖 strtok_s()或 POSIX 的 strtok_r() ,那么我建议避免 strtok()共。您可以基于 strcspn() 构建解决方案相反,这种替代方法也可能比您的方法更有效,因为它不需要任何 strlen()调用。

关于c - 显式使用 strtok 是否足以使其可重入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48085000/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com