为什么遗留strcpy()中没有健全性检查

时间:2010-09-01 08:40:19

标签: c++ c strcpy

以下是传统系统中最流行的strcpy实现。为什么在开始时没有检查dest和src是否为NULL?我曾经听说过,在过去,记忆力有限,所以短代码总是首选。你现在可以在开始的几天用NULL指针检查实现strcpy和其他类似的函数吗?为什么不呢?

char *strcpy(char *dest, const char *src)
{
   char *save = dest;
   while(*dest++ = *src++);
   return save;
}

9 个答案:

答案 0 :(得分:20)

NULL是一个糟糕的指针,但(char*)0x1也是如此。它还应该检查吗?在我看来(我不知道明确的原因),在这种低级操作中进行健全性检查是不必要的。 strcpy()非常基础,应该像asm指令一样对待,如果需要,你应该在调用者中进行自己的健全性检查。只是我2美分:))

答案 1 :(得分:15)

没有健全性检查,因为C最重要的潜在意识形态之一就是开发人员提供了理智。当你认为开发人员是理智的时候,你最终会得到一种可以用来做任何事情的语言。

这不是一个明确规定的目标 - 很可能有人想出一个检查这个的实现,等等。也许他们有。但我怀疑许多习惯于C的人会吵着要使用它,因为如果他们的代码有可能被移植到更常见的实现中,他们还是需要把支票放进去。

答案 2 :(得分:11)

整个C语言都写着“如果程序员知道他在做什么,我们会正确行事”。程序员应该知道他需要做出的所有检查。它不只是检查NULL,而是确保dest指向足够的已分配内存来保存src,它正在检查fopen的返回值,以确保文件确实 < / em>成功打开,知道memcpy何时是安全的,何时需要memmove,等等。

strcpy检查NULL不会改变语言范例。您仍然需要确保dest指向足够的空间 - 这是strcpy 无法在不更改界面的情况下检查的内容。您还需要确保src'\0'终止,而strcpy无法检查。

有一些C标准库函数检查NULL:例如,free(NULL)总是安全的。但总的来说,C希望你知道你在做什么。

[C ++通常会回避<cstring>库,转而支持std::string和朋友。]

答案 3 :(得分:6)

  1. 通常情况下,图书馆最好让调用者决定它想要的失败语义。如果任一参数为{{1},你会strcpy做什么}}?默默地什么都不做?失败NULL(在非调试版本中不是一个选项)?

  2. 选择加入比选择退出更容易。assert周围编写自己的包装来验证输入并使用它是很简单的。但是,如果图书馆自己这样做了,那么除了重新实施strcpy之外,你无法选择不执行这些检查。 (例如,您可能已经知道传递给strcpy的参数不是strcpy,如果您在紧密循环中调用它或关注它,它可能是您关心的事情最大限度地减少用电量。)一般来说,最好是在给予更多自由的情况下犯错(即使这种自由带来额外的责任)。

答案 4 :(得分:3)

最可能的原因是:因为未指定strcpy使用NULL输入(即在此情况下其行为未定义)。

那么,如果传入NULL,库实施者应该选择做什么?我认为最好的办法是让应用程序崩溃。可以这样想:崩溃是一个相当明显的迹象,表明出现了问题......另一方面,默默地忽略NULL输入可能会掩盖一个更难以发现的错误。

答案 5 :(得分:2)

未实现NULL检查,因为C的最早目标支持强内存保护。当进程尝试读取或写入NULL时,内存控制器会向CPU发出信号,表示尝试了超出范围的内存访问(分段违例),内核将终止有问题的进程。

这是一个很好的答案,因为尝试读取或写入NULL指针的代码被破坏了;唯一的答案是重新编写代码以检查来自malloc(3)和朋友的返回值并采取纠正措施。当你尝试使用指向未分配内存的指针时,就如何解决这种情况做出正确的决定为时已晚。

答案 6 :(得分:0)

您应该将C标准库函数视为汇编代码上方最薄的附加抽象层,您不希望这些抽象层可以将您的东西放在门外。除此之外的所有内容,例如错误检查,都是您的责任。

答案 7 :(得分:0)

据我所知,你想要定义的任何函数都有一个前置条件和一个后置条件。 照顾前提条件永远不应成为功能的一部分。以下是使用手册页中的strcpy的前提条件。

  

strcpy()函数将src指向的字符串(包括终止的'\ 0'字符)复制到dest指向的数组。字符串可能不重叠,目标字符串dest必须足够大才能接收副本。

现在如果不满足前提条件,那么事情可能是未定义的。

我现在是否会在strcpy中包含NULL检查。我宁愿有另一个safe_strcpy,给安全性优先级我肯定会包括NULL检查和处理溢出条件。因此我的前提条件得到修改。

答案 8 :(得分:0)

根本没有为其定义语义错误。特别是strcpy无法返回错误值。 C99只是声明:

  

strcpy函数返回值   s1

因此,对于符合要求的实现,甚至不可能返回出错的信息。那么为什么要烦恼呢。

我认为这一切都是自愿的,因为strcpy被大多数编译器直接替换为非常高效的汇编程序。错误检查取决于调用者。