2011-09-16 179 views
1
struct x { 
    int *u; 
}; 

struct y { 
    struct x *z; 
}; 

int main() 
{ 
    static y b; 
    static int g=7; 
    b.z->u=&g; 
} 

语句b.z->u=&g给出了分段错误。如果我删除static前面的int g通过嵌套结构访问指针

int g=7; 
b.z->u=&g; 

代码正确执行。

+0

无法理解为什么它会以这种方式发生。也有任何其他的上述分配.. – karan

+2

这个时候的每个答案都指出,b结果的静态分配在bz中设置为未定义的值。事实上,静态保证零初始化内存,所以b.z是NULL。如果你删除了关键字static,那么你会得到一个更糟的错误,其中b.z指向内存中的某个随机位置,也许argv被存储的位置等。 –

+1

@Heath Hunnicutt:不正确。首先,我的回答和评论从一开始就虚构了指针为空。其他答案也是如此。其次,OP在其中一个评论中明确提出了关于同一事物的非静态版本。 – AnT

回答

1

它会给你一个分割错误,因为你在做什么是未定义的行为。您正在访问z结构的指针,而不是对其进行初始化(即,不给它指向的内存空间)。在变量不是静态的情况下,它不会给出分段错误并不重要,因为对未初始化指针的整体访问是错误的。

+1

严格来说,由于'b'被声明为'static',所以保证被初始化为零。 'b.z'保证是一个空指针。当然,行为仍然是不确定的。 – AnT

1

您从未为您的b.z分配内存。您的b.z包含未初始化的垃圾值,这就是为什么试图废除b.z(在b.z->u中)会导致分段错误的原因。

P.S.你宣布你的对象static,这意味着b.z最初包含一个空值(不是“未初始化的垃圾值”,如上所述)。尽管如此,解引用空指针也是未定义的。

+0

但分配给非静态分配的工作? – karan

+1

@karan:什么是“非静态分配”?如果你删除'静态'?不,它不“工作”。如果它没有崩溃,那只是因为你以某种方式得到了幸运,并且垃圾值最终指向了一些可写的内存,随后你就会破坏它。 – AnT

+1

@karan - 不,它可能会出现*工作,但原因很微妙,事实是您的代码有一个可怕的错误,因为b.z永远不会被初始化。奥利的回答很好。静态的原因澄清你的bug是静态保证零初始化变量。这将b.z设置为NULL指针,并且会得到一个很好的,确定性的崩溃。当b被分配非静态时,它从先前堆栈中的任何内容接收内容。在这种情况下,b.z可以获得值NULL,或者一些非指针值或其他有效指针(然后使用b.z将覆盖另一个指针的内存)。 –

2

因为b.z尚未设置为指向任何有用的位置。它目前只是一个NULL指针。 *

您需要的线沿线的做一些事情:

b.z = malloc(sizeof(*b.z)); 

第一(即创建一个实际的对象)。

请记住在free这个点上。


*请注意,这只是因为NULLb声明为static。如果b不是static,它将指向内存中随机的某处。

+0

Downvoter:关心评论? –

+0

看起来像有人不喜欢这个问题,并想要每个人回答它。我想今天在Youtube上没有什么好处。 –

2

b.z尚未初始化。您初始化b有:

static y b; 

但其成员场z仍然是一个空指针(指向这样一些随机的位置)。因此,访问其成员u会导致分段错误,因为您正在访问一些随机存储器。

我想,这应该工作(没有尝试):

static y b; 
static x c; 
static int g=7; 
b.z = &c; 
b.z->u=&g; 

为什么你的第二个例子的作品,我不知道。我怀疑这是由于'运气'...