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

时间:2019-01-18 15:55:32

标签: c string pointers undefined-behavior string-literals

我正在阅读常见的C陷阱,并在some famous Uni website上发表了这篇文章。 (这是Google上出现的第二个链接)。

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

// 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;
}

评论中的解释让我开始思考,那不是字符串文字的记忆不是一成不变的吗?

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

进一步搜索后,我看到了一个问题:referencing a char that went out of scope,从这个问题中我了解到,以下是有效的代码。

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

int main() {
    puts(a);
}

question也同意另一个stackoverflow问题和我的想法,但反对该网站代码中的注释。

要对其进行测试,我尝试了以下方法,

#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;
}

它不会产生分段错误。

3 个答案:

答案 0 :(得分:3)

标准说(强调是我的):

  

6.4.5字符串文字

     
    
        
  1. [...]然后使用多字节字符序列初始化静态存储持续时间数组,长度足以容纳该序列。 [...]

  2.     
  3. [...] 如果程序尝试执行以下操作:     修改这样的数组,其行为是不确定的。 [...]

  4.     
  

答案 1 :(得分:2)

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

崩溃的原因是字符串文字是只读的。实际上,Manifest-Version: 1.0 Logging-Profile: myAppLogProfile 是C ++中的错误,应为char* x = ""。从语言的角度来看,它们是只读的,任何对其进行修改的尝试都将导致未定义的行为。

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

答案 2 :(得分:1)

字符串文字通常放在Product文件的rodata部分(只读)中,在Linux \ Windows \ Mac-OS下,它们将最终位于一个内存区域中,该内存区域将生成写入时出错(加载时操作系统配置为使用MMU或MPU)