C 在该程序的哪一点,我们将收到分段错误?
我得到了下面的代码,并被问到在什么时候我们会得到一条消息,说分割错误已经发生C 在该程序的哪一点,我们将收到分段错误?,c,C,我得到了下面的代码,并被问到在什么时候我们会得到一条消息,说分割错误已经发生 #include <stdlib.h> #include <string.h> #include <stdio.h> struct N { struct N *n; char *q; int a; } *q; int foo(void) { N *p = malloc(sizeof *p); p->a = 42; p->q = "life,␣universe,
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct N {
struct N *n;
char *q;
int a;
} *q;
int foo(void) {
N *p = malloc(sizeof *p);
p->a = 42;
p->q = "life,␣universe,␣everything";
p->n = (struct N *)p;
q = p;
free(p);
return 1;
}
int main() {
free( strcpy((char *)malloc(20),foo() + "Hello,␣World\n"));
(void) printf("q=%p\n", q);
(void) printf("q->a=%d\n", q->a);
(void) printf("q->q=%s\n", q->q);
return 0;
}
#包括
#包括
#包括
结构{
结构N*N;
char*q;
INTA;
}*q;
int foo(无效){
N*p=malloc(sizeof*p);
p->a=42;
p->q=“生活,␣宇宙,␣“一切”;
p->n=(结构n*)p;
q=p;
自由基(p);
返回1;
}
int main(){
free(strcpy((char*)malloc(20),foo()+“你好,␣世界),;
(无效)printf(“q=%p\n”,q);
(void)printf(“q->a=%d\n”,q->a);
(void)printf(“q->q=%s\n”,q->q);
返回0;
}
答案是,它只会发生在主体部分中倒数第二行之后,(void)printf(“q->q=%s\n”,q->q)代码>
有人能确切地解释一下为什么会发生这种情况吗
非常感谢。一个更正确的表达问题的方式是“程序的行为何时变得未定义”,或者“分段错误可能发生的第一个位置是什么”
因此,要回答这个问题:
以这一行为例:
free(strcpy((char*)malloc(20),foo()+“你好,␣世界),代码>
编辑(删除此项):此行不敏感。将int
添加到文本char*
并不意味着什么。我的C编译器发出警告并继续运行,所以我也会这样做
编辑(添加此项):正如注释中指出的,foo()
返回1,因此这将传递给“ello,␣World\n“
到strcpy。这是可以的,因为这少于分配的20个字符。这在我的C编译器中是一个警告,因为它很奇怪
问题是:这是否少于20字节。我认为是这样?因此,这一行基本上只是具有调用foo()
foo
只是乱七八糟的代码——但我会在其中添加注释,看看其中是否有未定义的部分:
int foo(void) {
// This is defined (added struct so it compiles)
struct N *p = malloc(sizeof *p);
// This is defined
p->a = 42;
// This is defined
p->q = "life,␣universe,␣everything";
// This is defined
p->n = (struct N *)p;
// This is defined
q = p;
// This is defined
free(p);
// Right now, q is pointing at free space -- it is very bad to derefence q
return 1;
}
返回到main()
(void)printf(“q=%p\n”,q)代码>
这将打印q
指针值——它不是解引用,因此没有问题
(void)printf(“q->a=%d\n”,q->a)代码>
我说这是没有定义的。显然,您正在解引用指向可用空间的q
q->a
是自由空间中的整数大小的位置,您正在阅读它。现在,如果内存没有被回收,这可能不是故障。它仍然不正确,也没有定义
现在,我们进入一条线路,您被告知will segfault:
(void)printf(“q->q=%s\n”,q->q)代码>
这是未定义的,原因与q->a
相同
当我运行它时,我得到
q=0x7fc30f4017c0
q->a=2
Segmentation fault: 11
所以,你看:它没有为q->a打印42,也没有进入下一行。程序没有定义,并且做了它允许做的事情之一,这是它想要做的任何事情。比如说
它可能打印错误的号码
它可能有故障
它可以完美地工作
它可能是一个安全漏洞的载体,它接管了你的机器,让黑客访问你的银行账户
这更好地解释了这一点:
更多:一个更正确的表达问题的方式是“程序的行为何时变得未定义”,或者“分段错误可能发生的第一个位置是什么”
因此,要回答这个问题:
以这一行为例:
free(strcpy((char*)malloc(20),foo()+“你好,␣世界),代码>
编辑(删除此项):此行不敏感。将int
添加到文本char*
并不意味着什么。我的C编译器发出警告并继续运行,所以我也会这样做
编辑(添加此项):正如注释中指出的,foo()
返回1,因此这将传递给“ello,␣World\n“
到strcpy。这是可以的,因为这少于分配的20个字符。这在我的C编译器中是一个警告,因为它很奇怪
问题是:这是否少于20字节。我认为是这样?因此,这一行基本上只是具有调用foo()
foo
只是乱七八糟的代码——但我会在其中添加注释,看看其中是否有未定义的部分:
int foo(void) {
// This is defined (added struct so it compiles)
struct N *p = malloc(sizeof *p);
// This is defined
p->a = 42;
// This is defined
p->q = "life,␣universe,␣everything";
// This is defined
p->n = (struct N *)p;
// This is defined
q = p;
// This is defined
free(p);
// Right now, q is pointing at free space -- it is very bad to derefence q
return 1;
}
返回到main()
(void)printf(“q=%p\n”,q)代码>
这将打印q
指针值——它不是解引用,因此没有问题
(void)printf(“q->a=%d\n”,q->a)代码>
我说这是没有定义的。显然,您正在解引用指向可用空间的q
q->a
是自由空间中的整数大小的位置,您正在阅读它。现在,如果内存没有被回收,这可能不是故障。它仍然不正确,也没有定义
现在,我们进入一条线路,您被告知will segfault:
(void)printf(“q->q=%s\n”,q->q)代码>
这是未定义的,原因与q->a
相同
当我运行它时,我得到
q=0x7fc30f4017c0
q->a=2
Segmentation fault: 11
所以,你看:它没有为q->a打印42,也没有进入下一行。程序没有定义,并且做了它允许做的事情之一,这是它想要做的任何事情。比如说
它可能打印错误的号码
它可能有故障
它可以完美地工作
它可能是一个安全漏洞的载体,它接管了你的机器,让黑客访问你的银行账户
这更好地解释了这一点:
更多信息:为了补充@Lou Franco的出色回答,我认为无论是谁提出这个问题,都会得到以下答案:
p->q = "life,␣universe,␣everything";
如果执行(void)printf(“q=%lu\n”,sizeof(q->q)),则将字符串
(在C中常量char*
)分配给未正确分配内存的结构中的指针,这只是指向char的指针
在大多数情况下(取决于系统),您会得到8,这是指向char
的指针的大小(分配的字节数),那么q->q
需要更多的字节,13似乎是我的测试允许的较小的大小,因此是