【发布时间】:2011-08-13 08:35:33
【问题描述】:
为什么strlen() 不检查 NULL?
如果我这样做strlen(NULL),程序分段错误。
试图理解其背后的基本原理(如果有的话)。
【问题讨论】:
-
请注意,大约 10 年前,strlen 和其他字符串函数在处理之前确实会检查空字符串,但由于大多数程序员无论如何都明确检查了这些指针,因此检查两次毫无意义。
标签: c segmentation-fault strlen
为什么strlen() 不检查 NULL?
如果我这样做strlen(NULL),程序分段错误。
试图理解其背后的基本原理(如果有的话)。
【问题讨论】:
标签: c segmentation-fault strlen
它背后的道理很简单——你如何检查不存在的东西的长度?
此外,与“托管语言”不同,运行时系统不期望正确处理无效数据或数据结构。 (这类问题正是为什么更“现代”的语言在非计算或性能要求较低的应用程序中更受欢迎的原因)。
c 中的标准模板如下所示
int someStrLen;
if (someStr != NULL) // or if (someStr)
someStrLen = strlen(someStr);
else
{
// handle error.
}
【讨论】:
someStr 应该指向一个字符串,那么当程序中的这个点到达时,它不应该是一个空指针。有些人使用空指针作为特殊的“空”值,但这不是通用约定,我会说它弊大于利...
strnlen_s(str, strsz) 会返回零。
语言standard 中定义字符串处理库的部分声明,除非为特定函数另行指定,否则任何指针参数必须 具有有效值。
C 标准库设计背后的理念是程序员最终处于了解是否真的需要执行运行时检查的最佳位置。回到以千字节为单位测量总系统内存的时代,执行不必要的运行时检查的开销可能非常痛苦。所以 C 标准库不会费心做任何这些检查;如果确实有必要,它假定程序员已经完成了它。如果您知道您永远不会将错误的指针值传递给strlen(例如,您传递的是字符串文字或本地分配的数组),那么就没有必要弄乱生成的二进制文件对 NULL 进行了不必要的检查。
【讨论】:
标准不要求它,因此实现只是避免测试和潜在的昂贵跳转。
【讨论】:
一个帮助你悲伤的小宏:
#define strlens(s) (s==NULL?0:strlen(s))
【讨论】:
strlens(p++)
三个重要原因:
标准库和 C 语言的设计假设程序员知道自己在做什么,因此空指针不被视为边缘情况,而是作为导致未定义行为的程序员错误;
它会产生运行时开销 - 调用 strlen 数千次并始终执行 str != NULL 是不合理的,除非程序员被视为娘娘腔;
它加起来会增加代码大小 - 它可能只有几条指令,但如果你采用这个原则并在任何地方都这样做,它可能会大大增加你的代码。
【讨论】:
NULL 输入,所以第一个原因是假的。第三个原因也是虚假的,因为在库中添加一些额外的检查(在典型的非嵌入式平台上)增加的代码大小比插入客户端代码中的所有检查要少。
NULL 并且这样的检查更像是 assert 语句时,原因三是有意义的。
NULL 的函数都在标准的“更新”部分(例如:mb*、wc*),不是吗?跨度>
size_t strlen ( const char * str );
http://www.cplusplus.com/reference/clibrary/cstring/strlen/
strlen 将指向字符数组的指针作为参数,null 不是此函数的有效参数。
【讨论】: