分割错误

我在这里看到了许多关于在C程序中获得分段错误的问题,我认为在这里有一个引用这些是很好的问题,在某些情况下会导致分段错误。 我的答案是张贴在下面。

正如在一些答案中所写的那样,所有情况下的行为都是不确定的,尽pipe很多人将它们视为分段错误 ,所以这个问题是关于什么导致这个“症状”的。

在下面的情况下,我运行程序时出现分段错误,您能确定原因吗?

1)

char *str = "foo"; str[0] = 'b'; // << Segfault hre 

2)

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

3)

 char *str = malloc(4 * sizeof(char)); str = "foo"; free(str); // << Segfault here 

4)

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

5)

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

6)

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

所有的例子都会导致不确定的行为,这可能会导致崩溃(或者可能看起来没有任何伤害)。

  1. 您不允许更改string文字。 (见这里 )

  2. 你忘了分配terminalnul字节的存储空间,做malloc(strlen(str) + 1);

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

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

  5. printf格式string中的%s告诉printf参数是一个string(一个char *,指向一个nul结尾的字符序列)你传递一个字符而不是一个string。 如果要打印string的后缀use printf("%s", &str[19]);

  6. 你传递一个无效的指针给free(),你已经释放了,当你做s->str时候,你不能解引用它。 反转释放顺序: free(s->str); free(s); free(s->str); free(s);

  1. 未定义的行为 :试图改变一个string文字
  2. 未定义行为 :写入数组的末尾
  3. 未定义的Bahaviour :传递给free()一个不是通过malloc()获得的指针
  4. 未定义的行为 :传递给free()一个无效的指针
  5. 未定义的行为printf()格式说明符和实际参数types之间的不兼容性
  6. 未定义的行为 :传递给free()一个无效的指针

未定义的行为可以通过“分段错误”performance出来,但这决不是必需的结果。 任何事情都可能发生:)

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

情况2:
strlen返回string的长度,在末尾没有'\0'字符,所以strlen("foo") = 3 ,而strcpy复制包含'\0'字符的string,因此它复制比分配的字节更多的字节。

情况3:
如情况1那样, str = "foo";str指定地址“foo”,这意味着你丢失了分配的内存地址,而str现在包含一个指向文本段的指针,由于它不在堆上,所以不能free ,因此它是只读的记忆。

案例4:
free函数不会将NULL指定给作为参数收到的指针(因为它没有它的地址,它不能这样做)。 而且你正尝试在已经free的缓冲区上free调用d。

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

情况6:
s->str之后s->str的用法是s->str d是错误的。 正确的用法是首先调用free(s->str); 然后free(s);通话free(s); 。 在free容器之前free内部分配的内存。

  1. 你还没有分配任何内存。 * str只是一个指针。
  2. 段错误的原因是在第2行,因为string分隔符'\ 0'需要malloc strlen()+ 1,

3:“foo”是一个常量string,不是dynamic分配的。

旁注:这也是内存泄漏。