分割错误
我在这里看到了许多关于在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
所有的例子都会导致不确定的行为,这可能会导致崩溃(或者可能看起来没有任何伤害)。
-
您不允许更改string文字。 (见这里 )
-
你忘了分配terminalnul字节的存储空间,做
malloc(strlen(str) + 1);
-
你在一个你没有从malloc(或类似函数)获得的指针上调用free()。 当你把
str
指针指向一个string文字时,你已经失去了指向malloc和泄漏内存的指针了。 -
你在同一个指针上调用free()两次,这是未定义的行为。
-
printf格式string中的%s告诉printf参数是一个string(一个char *,指向一个nul结尾的字符序列)你传递一个字符而不是一个string。 如果要打印string的后缀use
printf("%s", &str[19]);
-
你传递一个无效的指针给free(),你已经释放了,当你做
s->str
时候,你不能解引用它。 反转释放顺序:free(s->str); free(s);
free(s->str); free(s);
- 未定义的行为 :试图改变一个string文字
- 未定义行为 :写入数组的末尾
- 未定义的Bahaviour :传递给
free()
一个不是通过malloc()
获得的指针 - 未定义的行为 :传递给
free()
一个无效的指针 - 未定义的行为 :
printf()
格式说明符和实际参数types之间的不兼容性 - 未定义的行为 :传递给
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
内部分配的内存。
- 你还没有分配任何内存。 * str只是一个指针。
- 段错误的原因是在第2行,因为string分隔符'\ 0'需要malloc strlen()+ 1,
3:“foo”是一个常量string,不是dynamic分配的。
旁注:这也是内存泄漏。