获取分段错误

MBy*_*ByD 15 c segmentation-fault access-violation

我在SO中看到了很多关于在C程序中获取分段错误的问题,我认为在这里引用这些是很好的,这是一些导致分段错误的问题.我的答案发布在下面.

正如在一些答案中所写,对于所有情况,行为都是未定义的,尽管许多人将它们视为 分段错误,因此这个问题是关于导致这种"症状"的原因.

在下面的例子中,当我运行程序时出现分段错误,你能确定原因吗?

1)

char *str = "foo";
str[0] = 'b';   // << Segfault hre
Run Code Online (Sandbox Code Playgroud)

2)

char str[] = "foo";
char *newStr = malloc(strlen(str));
strcpy(newStr, str);
free(newStr);   // << Segfault here
Run Code Online (Sandbox Code Playgroud)

3)

char *str = malloc(4 * sizeof(char));
str = "foo";
free(str);      // << Segfault here
Run Code Online (Sandbox Code Playgroud)

4)

char *str = malloc(4 * sizeof(char));
strcpy(str, "foo");
free(str);
if (str != NULL)
    free(str);      // << Segfault here
Run Code Online (Sandbox Code Playgroud)

5)

char *str = "something and then foo";
printf("%s", str[19]);    // << Segfault here
Run Code Online (Sandbox Code Playgroud)

6)

typedef struct {
    char *str;
}st;
...
st *s;
s = malloc(sizeof(st));
s->str = malloc(5);
free(s);
free(s->str);    // << Segfault here
Run Code Online (Sandbox Code Playgroud)

nos*_*nos 9

您的所有示例都会导致未定义的行为,这可能会导致崩溃(或者可能根本不会造成任何伤害).

  1. 您不能更改字符串文字.(见例如这里)

  2. 你忘了为终止的nul字节分配存储空间了 malloc(strlen(str) + 1);

  3. 你在一个你没有从malloc(或类似函数)获得的指针上调用free().当你使str指针指向一个字符串文字时,你已经丢失了指向分配了malloc和内存泄漏的内存的指针.

  4. 你在同一个指针上调用free()两次,这是未定义的行为.

  5. printf格式字符串中的%s告诉printf该参数是一个字符串(指向nul终止字符序列的char*)您传递的是char,而不是字符串.如果要打印字符串的后缀使用printf("%s", &str[19]);

  6. 你传递了一个指向free()的无效指针,你已经自由了,你以后就不能取消s引用它了s->str.反转释放的顺序:free(s->str); free(s);

  • 你是说`malloc(strlen(str)+ 1);`?对于4:诀窍是`free()`不会将传递给它的指针设置为NULL,如果这是您想要的行为,则必须自己执行。 (2认同)

MBy*_*ByD 5

情况1:
char *str = "foo";在只读的文本段中分配一个字符串的地址,您不能像第二行那样写入它:str[0] = 'b';。如果要修改文本,请使用char str[] = "foo";which 将在堆栈上创建一个字符数组并将其指针分配给 str。

情况 2:
strlen返回末尾没有字符的字符串的长度'\0',因此strlen("foo") = 3,while 会strcpy复制包含'\0'字符的字符串,因此它复制的字节数比您分配的字节数多。

情况 3:
与情况 1 一样,str = "foo";将“foo”的地址分配给str,这意味着您丢失了已分配内存的地址,str现在包含一个指向文本段的指针,free因为它不在堆上,因此您不能这样做,并且它是一个只读存储器。

情况 4:
free函数不会分配NULL给作为参数接收的指针(因为它没有地址,所以不能这样做)。而你正试图调用free一个已经是freed的缓冲区。

情况 5:
str[19] is char,不是字符指针,并且"%s"需要字符串,意思是char *. 在许多平台上被视为地址,这个字符是非法地址。printf()不检查收到的参数。

case 6: after is d
的用法是错误的。正确的用法是先调用然后调用。在容器之前释放内部分配的内存。s->strsfreefree(s->str);free(s);free