【问题标题】:strlen not checking for NULLstrlen 不检查 NULL
【发布时间】:2011-08-13 08:35:33
【问题描述】:

为什么strlen() 不检查 NULL?

如果我这样做strlen(NULL),程序分段错误。

试图理解其背后的基本原理(如果有的话)。

【问题讨论】:

  • 请注意,大约 10 年前,strlen 和其他字符串函数在处理之前确实会检查空字符串,但由于大多数程序员无论如何都明确检查了这些指针,因此检查两次毫无意义。

标签: c segmentation-fault strlen


【解决方案1】:

它背后的道理很简单——你如何检查不存在的东西的长度?

此外,与“托管语言”不同,运行时系统不期望正确处理无效数据或数据结构。 (这类问题正是为什么更“现代”的语言在非计算或性能要求较低的应用程序中更受欢迎的原因)。

c 中的标准模板如下所示

 int someStrLen;

 if (someStr != NULL)  // or if (someStr)
    someStrLen = strlen(someStr);
 else
 {
    // handle error.
 }

【讨论】:

  • “托管”... 没错。想象一下,每个函数都开始非常偏执并检查每个可能的错误。 Printf 存储列表中每个参数的元信息,每个数学运算检查溢出等。这是管理的。
  • 我不同意“标准模板”。如果someStr 应该指向一个字符串,那么当程序中的这个点到达时,它不应该是一个空指针。有些人使用空指针作为特殊的“空”值,但这不是通用约定,我会说它弊大于利...
  • @R 我想我们对“标准模板”的含义并不一致。也许您更喜欢“有用的模式”?如果您对这个词感觉更好,我可以接受。
  • 在 c11 中,如果 str 是空指针,strnlen_s(str, strsz) 会返回零。
  • @jfs 它所做的不仅仅是它还限制了返回的最大大小。但是你说得很好,这显然是健壮程序的更好选择。
【解决方案2】:

语言standard 中定义字符串处理库的部分声明,除非为特定函数另行指定,否则任何指针参数必须 具有有效值。

C 标准库设计背后的理念是程序员最终处于了解是否真的需要执行运行时检查的最佳位置。回到以千字节为单位测量总系统内存的时代,执行不必要的运行时检查的开销可能非常痛苦。所以 C 标准库不会费心做任何这些检查;如果确实有必要,它假定程序员已经完成了它。如果您知道您永远不会将错误的指针值传递给strlen(例如,您传递的是字符串文字或本地分配的数组),那么就没有必要弄乱生成的二进制文件对 NULL 进行了不必要的检查。

【讨论】:

  • +1 表示“如果你知道你永远不会传递错误的指针值”。
  • “部分”为 C17 7.1.4.1。
【解决方案3】:

标准不要求它,因此实现只是避免测试和潜在的昂贵跳转。

【讨论】:

    【解决方案4】:

    一个帮助你悲伤的小宏:

    #define strlens(s) (s==NULL?0:strlen(s))
    

    【讨论】:

    • 只是不要调用它strlens(p++)
    • 首先避免使用宏。
    【解决方案5】:

    三个重要原因:

    • 标准库和 C 语言的设计假设程序员知道自己在做什么,因此空指针不被视为边缘情况,而是作为导致未定义行为的程序员错误;

    • 它会产生运行时开销 - 调用 strlen 数千次并始终执行 str != NULL 是不合理的,除非程序员被视为娘娘腔;

    • 它加起来会增加代码大小 - 它可能只有几条指令,但如果你采用这个原则并在任何地方都这样做,它可能会大大增加你的代码。

    【讨论】:

    • 一些标准 C 函数确实会检查 NULL 输入,所以第一个原因是假的。第三个原因也是虚假的,因为在库中添加一些额外的检查(在典型的非嵌入式平台上)增加的代码大小比插入客户端代码中的所有检查要少。
    • @larsmans:原因不是终极陈述,而是试图描述 C 编程中流行的思维方式;当您确定客户端代码中的指针不能是 NULL 并且这样的检查更像是 assert 语句时,原因三是有意义的。
    • @larsmans: 哦,但是大多数检查NULL 的函数都在标准的“更新”部分(例如:mb*wc*),不是吗?跨度>
    • @ninjalj:检查 NULL 实际上是 wc/mb 接口中最大的缺陷。这些函数的一个共同需求是一次处理一个字节/字符,并且对每次调用执行多个无用的空指针检查很容易使它们花费的时间加倍。
    • @R..:当然,我只是指出这些功能的存在并不真正构成 Blagovest 第一点的反例。
    【解决方案6】:
    size_t strlen ( const char * str );
    

    http://www.cplusplus.com/reference/clibrary/cstring/strlen/

    strlen 将指向字符数组的指针作为参数,null 不是此函数的有效参数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多