我是否误解了这个关于字符串文字范围的例子?

Do I misunderstand this example about scope of string literals?

我正在阅读常见的 C 陷阱,并在 some famous Uni website 上找到了这篇文章。 (这是 google 上出现的第二个 link。

该页面上的最后一个示例是,

// Memory allocation on the stack
void b(char **p) {
    char * str="print this string";
    *p = str;
}

int main(void) {
    char * s;
    b(&s);
    s[0]='j'; //crash, since the memory for str is allocated on the stack, 
              //and the call to b has already returned, the memory pointed to by str 
              //is no longer valid.
    return 0;
}

评论中的解释让我想到,字符串文字的内存不是静态的吗?

那里的实际错误不是您不应该修改字符串文字,因为它是未定义的行为吗?或者那里的评论是否正确,我对那个例子的理解是错误的?

进一步搜索后,我看到了这个问题:,我从那个问题中了解到,以下是有效代码。

#include <malloc.h>
char* a = NULL;
{
    char* b = "Whosebug";
    a = b;
}

int main() {
    puts(a);
}

此外,这个 question 同意其他 Whosebug 问题和我的想法,但反对该网站代码的评论。

为了测试它,我尝试了以下方法,

#include <stdio.h>
#include <malloc.h>

void b(char **p)
{
    char * str = "print this string";
    *p = str;
}

int main(void)
{
    char * s;
    b(&s);
    // s[0]='j'; //crash, since the memory for str is allocated on the stack,
                //and the call to b has already returned, the memory pointed to by str is no longer valid.
    printf("%s \n", s);
    return 0;
}

正如预期的那样,不会出现分段错误。

字符串字面量通常放在 ELF 文件的 rodata 部分(只读),在 Linux\Windows\Mac-OS 下,它们最终会出现在一个内存区域中,该区域将生成写入时出现故障(加载时 OS 使用 MMU 或 MPU 配置)

不对,你误解了崩溃的原因。字符串文字具有静态持续时间,这意味着它们在程序的生命周期内存在。由于您的指针指向文字,因此您可以随时使用它。

崩溃的原因是字符串文字是只读的。事实上 char* x = "" 在 C++ 中是一个错误,因为它应该是 const char* x = ""。从语言的角度来看,它们是只读的,任何修改它们的尝试都会导致未定义的行为。

实际上,它们通常放在只读段中,因此任何修改尝试都会触发 GPF - 一般保护错误。对 GPF 的通常响应是程序终止 - 这就是您在应用程序中看到的情况。

标准说(强调是我的):

6.4.5 String literals

  1. [...] The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence. [...]

  2. [...] If the program attempts to modify such an array, the behavior is undefined. [...]