关于修改 char * 元素的 SIGSEGV

SIGSEGV on modifying char * element

在下面的程序中,

#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 也是常量字符串文字吗

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

上是这样

事情就是这样:

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

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

  3. 你试试改"def"

  4. 您无法释放内存,因为当您将 str2 分配给 "def"

    [= 的地址时,您实际上丢失了它的地址32=]

按照 C 标准

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

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


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


  str2= "def";

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

如果你想将 "def" 存储到 malloced space 然后使用 memcpy 的 strcpy.

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

问题:

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

This means that you have asked for 4 bytes of space in the memory for your personal use and you have been granted with the starting address of the space.

  str2= "def";

You got your personal address but now you are changing your address to point to the enchanting "def" which belongs to Read-Only Data section of the memory (String literals). This means that the original address allocated is dangling and cannot be traced back.

问题:

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

str2[1]='s';

Ohh and now you are trying to be a rebel by trying to change the read only section's content.

问题:

  • 正在尝试覆盖不允许的只读段。

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

您可能正在尝试的是:

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