【问题标题】:Static C string allocation question静态C字符串分配问题
【发布时间】:2011-04-20 02:19:42
【问题描述】:

考虑以下代码:

char* str = "Hello World";
memcpy(str, "Copy\0", 5);

在 memcpy 期间发生分段错误。但是,使用此代码:

char str[12];
memcpy(str, "Hello World\0", 12);
memcpy(str, "Copy\0", 5);

程序不会产生分段错误。

问题是否来自于在堆栈上分配内存而不是在数据段上分配内存?

【问题讨论】:

  • 为什么是双空?字符串文字已经包含终止符 \0,正如您在 sizeof "foobar" 中看到的那样。

标签: c string memory-management


【解决方案1】:

当您在 gcc 中使用字符串文字时,该值被放置在只读内存中并且无法修改。试图修改它会导致未定义的行为。当您尝试这样做时,通常会在 Linux 上遇到分段错误。

第二个示例有效,因为您没有修改字符串文字,而是修改了存储在非只读变量中的它的副本。

【讨论】:

  • +1 标准规定 (6.4.5/6) “如果程序试图修改这样的数组,则行为未定义。”虽然没有提到只读内存(它很可能适用于 Linux 和 gcc)
  • "Hello, World" 的含义是数组是一个 const char *。当然,您可以使用常规 char * 指向 const char *。如果你调高 gcc 的警告级别,它当然会抱怨这一点。但是,数据仍然无法修改。
  • @pmg:当标准说某些行为未定义时,这意味着(至少就标准而言)符合标准的实现可以做ANYTHING。重新格式化硬盘驱动器,触发热核世界末日等。如果程序员得到的只是分段错误,她很容易下车。
  • 在许多情况下,“未定义行为”情况是那些需要硬件支持的情况。在这种情况下,它支持内存访问权限。
  • @KFro:字符串文字的类型是 C 中的 char [n],而不是 const char [n]。在 C++ 中情况有所不同。
【解决方案2】:
char* str = "Hello World";

char str[12];

是两个非常不同的东西。一个在堆栈上分配一个指针,并在只读“代码段”中分配一个数组。然后指针指向数组。另一个在栈上分配整个数组,没有指针。

【讨论】:

  • 请有人确认一下。 str 是否存储在代码段中?我认为它在数据部分。
  • 其实叫rdata
  • 对不起,我的措辞不好。静态常量数据和代码段是单独的段。但是两者的内存都不能修改。
  • 实际上它的实现定义了字符串常量是在代码段中,在常量数据段中还是在可修改的初始化数据段中。
  • @PaulStelian:非常正确。对于那些确实使差异很重要的实现,了解差异仍然是值得的。
猜你喜欢
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 2021-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多