2011-04-18 63 views
0

这两个函数都是(至少在我的编译器下)保证会创建一个seg错误,但我不知道为什么。我真的很喜欢他们的功能,我也看到了类似的例子,所以我很想知道这里出了什么问题,或者怎么做,我认为这实际上是做什么的,它将一个“级”传递给某个函数,然后能够操纵其变量(例如lvl.lvl_cl [X] [Y] [Z] = some_number),然后传递回用于进一步使用将结构传递给一个函数会创建一个默认错误

任何帮助理解:)

typedef struct { 
    int lvl_cl[500][500][50]; 
    char lvl_ch[500][500][50]; 
} level; 

level plugh(level * in_lvl){ 
    in_lvl->lvl_cl[444][444][44]++; //it segfaults even if this line is removed 
    return * in_lvl; 
} 

level foo(level inlvl){ 
    inlvl.lvl_cl[443][443][43]++; //it segfaults even if this line is removed 
    return inlvl; 
} 

int main(void){ 
    level world; 
    plugh(&world); 
    foo(world); 
    return 0; 
    } 
+0

12.000 KO值int。哇!阅读您的评论。使用类似这样的方式:将'level'定义为'* level',并使用'new'关键字在堆上创建对象。它绝对会帮助你。 – 2011-04-18 19:54:11

+0

你知道你的结构没有被初始化吗? – 2011-04-18 20:03:53

+1

@AdrianMar这是一个C的问题。 – 2011-04-18 20:06:11

回答

0

每当您拨打foo函数时,它会复制整个world结构,它非常大。尝试通过指针:

void foo(level *inlvl){ 
    inlvl->lvl_cl[443][443][43]++; 
} 
+0

好吧,它远不止于此。 C没有参考。即使他们做了,也有一个堆栈分配的结构实例。 – 2011-04-18 20:07:02

+0

当我尝试编译上述代码之前,不能通过引用传递它是因为它在'&'标记之前说的“...:错误:预计';',','或')' – Jacob 2011-04-18 20:17:52

+0

同意,改为指针 – Elalfer 2011-04-18 20:18:49

3

堆栈溢出?

说真的,你有没有考虑过你的结构有多大?如果将它存储在堆栈中,它会溢出...

尝试一个sizeof(level),看到实际大小会很有趣。

编辑:如果你需要的东西很大,你真的应该考虑你在哪里以及如何存储它。如果你将它传递给一个函数,你将制作一个拷贝的结构并将它放在堆栈中。如果你返回结构体,你很可能需要另一个堆栈副本。

你真的需要传递并返回结构吗?如果没有,你可以把它放在正常的静态存储器(一个普通的全局变量)或在堆上分配一个。无论哪种方式,如果传递一个指向它的指针,它只会占用全部结构的一小部分。

+0

我的一半问题是我需要它那么大......这实际上是来自世界[10] [1000] [1000] [1000] [100] [10] lol – Jacob 2011-04-18 19:53:16

+3

相信我,你不需要它那么大。你需要使用malloc进行分配,以便堆放在堆上而不是堆栈中。 – 2011-04-18 19:57:16

+2

你确定*你需要一个大的数据结构吗?你知道'int world [10] [1000] [1000] [1000] [100] [10]'有10万亿个元素,对吗? – 2011-04-18 20:00:28

1

问题是,你在堆栈上放置了大约100MB,你的堆栈并不大。

您需要开始使用指向level结构和堆分配的指针,而不是试图将其复制到堆栈中!

2

首先,这是存储器的LOT:

500x500x50x1(因为1个字节在炭)+ 500x500x50x4(因为在一个int 4个字节)=的存储器 59.605MB。

您将这些全部存储在堆栈中,而不是使用指针并将其分配到堆上,这会导致堆栈溢出。

此外,在你的plugh和foo函数中,你正在返回一个全新的结构。为什么通过指针传递,修改对象,然后返回一个副本?每次调用这些函数时,都会分配另一个59.605MB的内存,因为您正在返回一个副本。但是,由于您没有使用该副本,因此编译器可能会优化并删除这些昂贵的副本。

+1

嗯,它甚至不止是因为对齐,100MB的最佳部分! – 2011-04-18 19:59:16

1

它出现segfaults

0x8048471 <main>:  lea 0x4(%esp),%ecx 
0x8048475 <main+4>:  and $0xfffffff0,%esp 
0x8048478 <main+7>:  pushl -0x4(%ecx) 
0x804847b <main+10>: push %ebp 
0x804847c <main+11>: mov %esp,%ebp 
0x804847e <main+13>: push %esi 
0x804847f <main+14>: push %ebx 
0x8048480 <main+15>: push %ecx 
0x8048481 <main+16>: sub $0xb2d060c,%esp 
0x8048487 <main+22>: lea -0x7735958(%ebp),%eax 
0x804848d <main+28>: lea -0x3b9acb8(%ebp),%edx 
0x8048493 <main+34>: mov %edx,0x4(%esp)  <<---- segfaults here 
0x8048497 <main+38>: mov %eax,(%esp) 
0x804849a <main+41>: call 0x80483f4 <plugh> 

分配的6250万个字节(32位int)堆栈帧后,在寻址新堆栈指针时,会出现故障。

大型结构应始终按引用传递。特别是考虑到foo()的逻辑。

+0

不只是通过引用传递,而是分配了堆。在main中查找堆栈分配的局部变量。 – 2011-04-18 20:07:32

0

你有没有试过一个只传递给你的结构并不返回任何结果的函数? 沿线的东西void foo(level * var){//您的代码在这里修改var} 而在main中,您只需调用foo(& myVar)。

将如此巨大的结构作为参数传递给函数或将其作为返回值可能会给您带来一些麻烦。另外,如果您确实需要返回值,请尝试返回对您的结构的引用。 like level * foo(level * in){//你的代码在这里}。

而在主要你只是解引用函数的结果像级别myLvl = *(foo(& myOtherLvl))。这样,你在你的函数中传递的所有东西都是你的结构,女巫基本上是整数。希望这可以帮助

相关问题