【问题标题】:C strcpy() copies string literals without segmentation faultC strcpy() 复制字符串文字而没有分段错误
【发布时间】:2019-05-16 22:12:55
【问题描述】:

据我了解,字符串文字存储在只读内存中,在运行时对其进行修改会导致分段错误,但我下面的代码编译时没有分段错误。

#include <string.h>
#include <stdio.h>

int main() {
  char* scr = "hello";
  strcpy(scr,scr);
  printf("%s\n",scr);
  return 0;
}

输出:你好

同样的事情,如果我尝试将源字符串复制到不同的目标字符串文字,则会引发分段错误

#include <string.h>
#include <stdio.h>

int main() {
  char* scr = "hello";
  char* dst = "hello";
  strcpy(dst,scr);
  printf("%s\n",dst);
  return 0;
}

输出:分段错误(核心转储)

根据 K&R 的书 strcpy() 实现类似于下面

void strcpy(char *s, char *t)
{
while ((*s = *t) != '\0') {
  s++;
  t++;
  }
}

如果是这样,我应该在这两种情况下都遇到分段错误。

编译器详情:

gcc 版本 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)

【问题讨论】:

  • 欢迎来到未定义行为的奇妙世界,它不必表现在段错误中。
  • strcpy 完全有可能检查您是否正在将字符串复制到自身并且什么都不做,这并没有使它变得更少未定义。

标签: c string segmentation-fault strcpy string-literals


【解决方案1】:

字符串文字存储在只读内存中,在运行时修改它会导致分段错误,

不,你错了。它调用undefined behaviour,分段错误是众多 UB 可能的影响之一。

引用 C11,第 §6.4.5/P7 章,字符串文字

[...] 如果程序试图修改这样的数组,行为是 未定义。

【讨论】:

    【解决方案2】:

    许多系统上的字符串文字都放置在 RO 内存位置。最流行的操作系统下最流行的编译器可以做到这一点(Windows、Linux、mac os 等)。但许多其他(例如 avr-gcc)没有。

    所以段错误并不是这个 UB 的唯一可能影响。

    但在您的情况下,我敢打赌编译器已经优化了 strcpy 调用,因为不需要将对象复制到自身。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-19
      • 1970-01-01
      • 1970-01-01
      • 2012-02-20
      • 1970-01-01
      • 1970-01-01
      • 2012-10-25
      • 2014-10-21
      相关资源
      最近更新 更多