【问题标题】:SIGSEGV on modifying char * element [duplicate]关于修改 char * 元素的 SIGSEGV [重复]
【发布时间】:2016-10-20 05:18:15
【问题描述】:

在下面的程序中,

#include<stdio.h>
#include<stdlib.h>
int main(){
  const char *str1 = "abc";
  char *str2 = (char *)malloc(sizeof(char)*4);
  str2= "def";
  str2[1]='s';
  printf("str2 is %s", str2);

}

调试器:

(gdb) ptype str1                                                                                                                         
type = const char *                                                                                                                      
(gdb) ptype str2                                                                                                                         
type = char *                                                                                                                            
(gdb) n                                                                                                                                  
7         str2[1]='s';                                                                                                                   
(gdb) n               

Program received signal SIGSEGV, Segmentation fault.                                                                                     
0x00000000004005ab in main () at main.c:7                                                                                                
7         str2[1]='s';                                                                                                                   
(gdb)

str2[1] = 's'; 上的 SIGSEGV

根据我的理解,由于声明const char *st1 = "abc",其中字符串文字是常量,因此无法修改st1 指向的abc

为什么char * 类型str2 不允许修改元素? stringliteral def 也是常量字符串文字。

【问题讨论】:

标签: c pointers malloc char-pointer


【解决方案1】:

事情就是这样:

  1. str2 分配有malloc() 并指向新分配的4个字符的缓冲区

  2. 您将str2 的值(地址)更改为"def" 的地址,这是只读的(将其视为程序的一部分)

  3. 您尝试更改"def"

  4. 您无法释放内存,因为当您将str2 分配给"def" 的地址时,实际上丢失了它的地址

【讨论】:

    【解决方案2】:

    按照 C 标准

    字符串文字("def") 将存储在数据部分的只读页面中。

    所以你不能修改它的内存。


    您可以修改str2 指针的内容。这意味着您可以将 str2 指向其他内存。但是分配给string literal "def"的内存不能修改。


      str2= "def";
    

    通过这样做,您不会在分配的内存中复制“def”。 相反,“def”被分配在只读区域中,您将其地址分配给 str2。

    如果您想将该“def”存储到分配空间中,请使用 memcpy 的 strcpy。

    【讨论】:

      【解决方案3】:

      str2 = "def"; 语句更改str2 的值。 str2 指向导致以下崩溃的赋值后的字符串文字“def”。至少,在我的 RHEL 7.1 和 gcc 4.8.3 上是这样的

      【讨论】:

        【解决方案4】:

        如果你想在你刚刚分配的字符串缓冲区中存储“abc”,你必须使用strcpy(),如strcpy(str2, "abc")。正如其他用户指出的那样,使用str2 = "abc" 将更改str2 指向的内存地址而不是这样做,并且该新地址是指无法修改的只读部分。

        【讨论】:

          【解决方案5】:

          问题:

            char *str2 = (char *)malloc(sizeof(char)*4);
          

          这意味着你在内存中申请了 4 个字节的空间供你个人使用,并且你已经获得了空间的起始地址。

            str2= "def";
          

          您获得了您的个人地址,但现在您将地址更改为指向迷人的“def”,该“def”属于内存的只读数据部分(字符串文字)。这意味着分配的原始地址是悬空的,无法追溯。

          问题:

          • 地址无法追踪的悬空指针。
          • 您将无法释放它。

          str2[1]='s';

          哦,现在您正试图通过更改只读部分的内容来成为反叛者。

          问题:

          • 试图覆盖不允许的只读段。

          • SIGSEGV 是原因,即由无效内存引用或分段错误引起的错误(信号)。

          你实际上可能在尝试什么:

          • 为您的工作分配内存(4 个字节)
          • 将内容覆盖到该内存strcpy(str2, "def");
          • str2[1] = 's' 也可以使用。
          • 请释放str2 变量,因为您是请求它的人。 (权力越大,责任越大);)

          【讨论】:

            猜你喜欢
            • 2012-10-07
            • 1970-01-01
            • 1970-01-01
            • 2013-11-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-12-12
            • 1970-01-01
            相关资源
            最近更新 更多