【发布时间】:2017-07-18 06:24:22
【问题描述】:
我正在重新创建整个标准 C 库,并且正在为 strlen 开发一个实现,我希望它成为我所有其他 str 函数的基础。
我目前的实现如下:
int ft_strlen(char const *str)
{
int length;
length = 0;
while(str[length] != '\0' || str[length + 1] == '\0')
length++;
return length;
}
我的问题是,当我通过 str 喜欢:
char str[6] = "hi!";
正如预期的那样,内存读取:
['h']['i']['!']['\0']['\0']['\0']['\0']
如果您查看我的实现,您可以预期我会得到 6 的回报 - 而不是 3(我之前的方法),因此我可以检查 strlen 可能包括额外分配的内存。
这里的问题是,我必须在初始化内存之外读取 1 个字节才能使最后一个循环条件在最终空终止符处失败 - 这是我想要的行为。然而,这通常被认为是不好的做法,并且在某些情况下会自动出错。
即使您非常明确地打算读取垃圾值(以确保它不包含“\0”),在您的初始化值之外读取是不是一个坏主意?
如果是,为什么?
我明白:
"buffer overruns are a favorite avenue for attacking secure programs"
不过,如果我只是想确保我已经达到初始化值的末尾,我看不出问题...
另外,我意识到这个问题是可以避免的——我已经回避了一个设置为 1 的值,然后只读取初始化值——这不是重点,这更多是关于 C、运行时行为和最佳实践的基本问题;)
[编辑:]
评论之前的帖子:
好的。很公平 - 但关于“在初始化值后读取是否总是一个坏主意(故意操纵或运行时稳定性的危险)”这个问题 - 你有答案吗?请阅读已接受的答案,以了解问题性质的示例。我真的不需要修复这段代码,也不需要更好地理解数据类型、POSIX 规范或通用标准。我的问题与为什么可能存在这样的标准有关 - 为什么永远不要读取过去的初始化内存(如果存在这样的原因)可能很重要?在 GENERAL 中读取过去的初始化值的潜在后果是什么?
请大家- 我正在尝试更好地了解系统如何运行的各个方面,我有一个非常具体的问题。
【问题讨论】:
-
无法保证数组后面的字节不为零,因此您的函数可能会超出缓冲区任意数量。或者它可能会遇到未映射到物理存储的地址并因段错误而崩溃。或者...(参见 UB)。
-
使用未初始化的变量被枚举为UB(未定义的行为)。
-
J.2 未定义行为 具有自动存储期限的对象的值在不确定时使用
-
没有“管理未定义的行为”这样的东西。未定义就是未定义,句号。
-
Also 6.5.6 加法运算符 p8 如果结果指向数组对象的最后一个元素之后,则不应将其用作计算的一元 * 运算符的操作数。 所以未定义就是未定义。每个动作都没有规定。
标签: c posix standards c-standard-library data-handling