gpt4 book ai didi

c - 为什么 strcpy 编译为文字?

转载 作者:行者123 更新时间:2023-12-02 08:21:53 25 4
gpt4 key购买 nike

在 Visual Studio 2015 中,编译以下内容:

strcpy("destination", "Source");

编译器难道不应该弄清楚“目的地”是一个字面量,不能构成一个有效的非常量 char* 参数吗?

作为旁注,它在运行时确实“正确地”崩溃了。

最佳答案

上下文

字符串字面量在 C 语言中一直是非常量。当前标准草案 n1570 在 6.4.5/6 中说:

The multibyte character sequence [resulting from concatenation of adjacent string literals, -ps] is then used to initialize an array of static storage duration and length just sufficient to contain the sequence. For character string literals, the array elements have type char [and not const char, -ps].

当然,原因是它们最初确实通常是可写的。程序本身是可写的;甚至还有自修改代码。这是相关的,因为字符串文字是由编译器“与程序一起”生成和存储的。

现代内存管理——即高级机器架构的问题——使得在访问程序内存时完全有可能生成硬件异常。使用这种可能性是一个安全问题。并非所有架构(都可以)做到这一点,即使在今天,编译器也可以选择控制字符串的位置(例如 -fwritable-strings with old gccs)。

本代码

代码在语法上是兼容的,在语义上它是 n1570 中 6.4.5/7 的 UB:“如果程序试图修改这样的数组,行为是未定义。”

当字符串文字的地址被分配给非常量变量(或用于初始化函数调用中的非常量参数)时,编译器可能会发出警告,但我尝试过的常见地址不会发出警告,这让我有点困惑——a许多已实现的警告似乎不那么重要且嘈杂。

strcpy()

关于 strcpy() 的细节:一些评论说“编译器不知道 strcpy() 做了什么”。这往往具有误导性:

  • 标准库函数由标准明确定义。这些知识可以在编译器中使用。例如,像 lint 这样的工具通常知道这样的语义。
  • 编译器和默认标准库通常是紧密合作开发的,并且是捆绑在一起的;因为在编译库本身、编译器引导等方面,编译器和库之间存在大量交互。两个项目之间通常会定期进行交流。
  • 编译器可以自由地将库函数替换为内部函数,这会给他们非常深入的知识。

海湾合作委员会

确实,gcc happens to replace strcpyand many other functions with built-ins,所以它确实有第一个地址将被写入的第一手信息。它只是不使用它。

另一个 gcc 内部函数是 printf(),编译器在这里使用它对 printf 语义的了解来警告格式错误。这清楚地表明 strcpy() 也可能发出警告。

顺便说一句,gcc 警告 "abc"[1] = 0;。这很有趣,因为我曾认为 strcpy() 内在函数会被内联(它必须很短),以便 -O3 和可能的 -flto 在某些时候相当于 "destination"[i] = "Source"[i]; 实际上对编译器可见并触发相同的警告。

其他编译器

我测试了 VC 2013、gcc 5.3.0、gcc 4.7.2 和 clang 3.7.1。它们都没有发出将字符串文字传递给 strcpy() 的警告,但 cremno 指出 VC 提供了捕获错误的 /analyze 选项。

关于c - 为什么 strcpy 编译为文字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36484833/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com