strlen是否具有未初始化值的字符串未定义行为?

时间:2014-09-12 01:22:59

标签: c string strlen

strlen返回终止空字符前面的字符数。 strlen的实现可能如下所示:

size_t strlen(const char * str)
{
    const char *s;
    for (s = str; *s; ++s) {}
    return(s - str);
}

此特定实现取消引用s,其中s可能包含不确定的值。它等同于:

int a;
int* p = &a;
*p;

例如,如果有人这样做(导致strlen输出错误):

char buffer[10];
buffer[9] = '\0';
strlen(buffer); 

是不确定的行为?

4 个答案:

答案 0 :(得分:2)

调用标准函数strlen会导致未定义的行为。 DR 451澄清了这一点:

  

库函数在用于不确定值时将显示未定义的行为

进行更深入的讨论see this thread

答案 1 :(得分:2)

在这种情况下,您所展示的变体的行为已明确定义。

  • 未初始化数组的字节具有所有不确定的值,但您设置为0的第10个元素除外。
  • 如果永远不会采用基础对象的地址,或者该值是相应类型的陷阱,则访问不确定的值只会是UB。
  • 由于这是一个数组,并且通过指针算法访问数组元素,因此第一种情况与此无关。
  • 可以在没有UB的情况下访问任何char值,标准中关于陷阱表示的子句明确排除了所有字符类型。
  • 因此,您正在处理的值只是"未指定"。
  • 根据C标准委员会的一些成员,每次给出不同的结果可能会给出不同的结果,有些人称之为" whobly"国家左右。此属性与此属性无关,因为您的函数最多只能读取一次这样的值。
  • 因此,您对数组元素的访问权限可为您提供任意但有效的char值。
  • 您确定for循环最迟在位置9处停止,因此您不会超出阵列。

所以没有"坏"如果您使用特定版本的功能,可能会发生超出可见范围的事情。但是有一个产生未指定结果的函数调用肯定不是你想在实际代码中看到的。这样的事情导致了非常微妙的错误,你应该尽一切可能避免它。

答案 2 :(得分:1)

不,它不是未定义的行为。您的strlen函数将在缓冲区结束前停止。如果你的strlen函数引用了buffer [10],那么,yes是未定义的。

肯定会出现意外行为,因为大多数缓冲区都包含随机数据。 "未定义"是人们写语言标准的特殊词汇。这意味着任何事情都可能发生,包括内存故障或退出程序。出乎意料的是,我的意思是确定程序员不想发生什么。在某些运行中,strlen的结果可能是3或者可能是10。

答案 3 :(得分:0)

是的,这是未定义的行为。从草案C11标准,§J.2“未定义的行为”:

  

在以下情况下,行为未定义:

     

...

     

使用具有自动存储持续时间的对象的值   不确定的。