【问题标题】:segmentation fault in c programc程序中的分段错误
【发布时间】:2011-05-23 22:26:08
【问题描述】:

只是为了测试,我创建了以下代码:

#include<stdio.h>

int main(){
    char *p = "Hello world";
    *(p+1) = 'l';
    printf("%s", p);
    return 0;
}

但是当我在 ubuntu 10.04 下的“gcc”编译器上运行它时,我得到了:

Segmentation fault

那么任何人都可以解释为什么会发生这种情况。

#include<stdio.h>
#include<stdlib.h>

int main(){
    char *p = malloc(sizeof(char)*100);
    p = "Hello world";
    *(p+1) = 'l';
    printf("%s", p);
    free(p);
    return 0;
}

这也会导致分段错误 提前致谢

【问题讨论】:

标签: c gcc segmentation-fault


【解决方案1】:

char *p = "Hello world"; *(p+1) = 'l';

修改字符串文字(即代码中的“Hello World”)的内容是未定义行为。

ISO C99(第 6.4.5/6 节)

如果这些数组的元素具有适当的值,则未指定这些数组是否不同。 如果程序试图修改这样的数组,则行为未定义

尝试使用字符数组。

char p[] = "Hello World";
p[1] = 'l'; 

编辑

你修改的代码

#include<stdio.h>
#include<stdlib.h>
int main()
{
   char *p = malloc(sizeof(char)*100);
   p = "Hello world"; // p now points to the string literal, access to the dynamically allocated memory is lost.
   *(p+1) = 'l'; // UB as said before edits
   printf("%s", p);
   free(p); //disaster
   return 0;
}

也会调用未定义行为,因为您正在尝试释放尚未使用 malloc 分配的内存部分(使用 free

【讨论】:

  • 嘿,请检查修改后的问题
  • ... 并且因为只读内存仍在修改中,因为在p = "Hello world" p 之后不再指向malloced 内存。
  • ok 那么这是否意味着先前分配的内存(通过 malloc)丢失了,现在我使用的是编译器为字符串文字“Hello world”分配的新内存部分。我说的对吗?
【解决方案2】:

因为char *p = "Hello world" 几乎肯定会给你一个指向只读内存的指针,这意味着尝试用*(p+1) = 'l' 更改它是绝对不行的(即使内存不是只读的,行为仍未定义)。

C99 中引用字符串字面量的相关部分在6.4.5 para 6:

如果这些数组的元素具有 适当的值。如果程序试图修改这样的数组,行为是 未定义。


仍然出现分段错误的原因如下:

char *p = malloc (100);  // sizeof(char) is ALWAYS 1
p = "Hello";             // better would be: strcpy (p, "Hello")
*p = 'a';

是因为,即使您分配了允许修改的内存,第二条语句也会将 pointer 更改为指向字符串文字(当您失去访问权限时会出现内存泄漏到分配的内存),不允许修改。

您需要区分对 指针 的更改与对指针所指位置的更改。

【讨论】:

  • 但是当我写 p = "Hii" 时。它没有问题。
  • 这是因为您将指针更改为指向另一个字符串文字,不是试图更改字符串文字本身。
  • 好的,但是如果内存是通过 malloc 分配的。正如我在问题的新代码部分所做的那样。
【解决方案3】:

"Hello world" 是一个字符串文字。它由不能修改的内存区域中的一大块字节表示。 char *p 指向那个字节块。 *(p+1) = 'l' 表示用“l”覆盖指向的字节之后的下一个字节。指向的字节之后的下一个字节是不可修改的块的一部分。试图覆盖某些东西就是试图修改它。试图修改不允许修改的东西是非常糟糕的。

为了在内存中获得可能修改的文本副本,请将其放入数组中,例如char p[] = "Hello world";。 (请注意,以这种方式声明数组会使它恰好大到足以容纳字符串,因此您可能不会延长它,因为没有更多空间了。)

【讨论】:

    猜你喜欢
    • 2012-10-12
    • 2018-11-18
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    • 2011-10-19
    • 2015-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多