2011-12-31 51 views
0

操作系统:Windows 7,编译器:GCC 3.2.3(MinGW的)C程序崩溃分配化合物结构

我已创建这三个数据结构在C:

#define MAP_NAME_LEN 30 
#define MAP_W   25 
#define MAP_H   19 
#define WORLD_W   32 
#define WORLD_H   32 

typedef unsigned char byte; 

typedef struct Tile 
{ 
    byte type; 
    byte character; 
    byte fgColor; 
    byte bgColor; 
}; 

typedef struct Map 
{ 
    char name[MAP_NAME_LEN]; 
    Tile overlay[MAP_H][MAP_W]; 
    Tile underlay[MAP_H][MAP_W]; 
}; 

typedef struct World 
{ 
    Map area[WORLD_H][WORLD_W]; 
}; 

当我尝试创建瓷砖和/或地图的个别实例,没关系,完全没有问题,一切正常。不过,如果我尝试创建一个世界,像...

int main() 
{ 
    World world; 
} 

...程序简单地崩溃(Windows 7中说,该程序崩溃或正在寻找一个解决方案,等等)。你们有什么想法为什么会这样?

谢谢!

+1

请发布MAP_NAME_LEN,MAP_H和MAP_W,WORLD_H和WORLD_W的值。可能堆栈溢出。 – hmjd 2011-12-31 21:02:58

+1

你使用的typedef没有声明defintion。你应该这样写:typedef struct _Map {...} Map;如果你喜欢,你也可以省略_Map,创建匿名结构。 – stdcall 2011-12-31 21:03:42

+0

什么是MAP_W/H WORLD_W/H定义为?也许你在堆栈上放太多? – 2011-12-31 21:03:31

回答

5

根据MAP_NAME_LENMAP_HMAP_WWORLD_H,并且WORLD_W,你可以创建一个庞大的结构在堆栈上的值。不要这样做。堆栈相对较小,通常不能处理总共几兆字节的分配(并且通常每次只能处理几十千字节的分配)。考虑到你的不变价值,你很可能会遇到这些限制 - 你的World结构几乎是4MB大,太大而不能合理地放在堆栈上。

所以,相反,与malloc它分配在堆上,或为全局或文件的本地静态变量:

World world; 

int main() 
{ 
    /* ... */ 
} 

int main() 
{ 
    World *world = malloc(sizeof(*world)); 
    /* ... */ 
    free(world); 
} 
+0

我刚刚编辑了代码以显示常量的值。 – 2011-12-31 21:06:35

2

我最好的猜测是你的World对象超过最大堆栈大小。这取决于您如何定义MAP_NAME_LENMAP_HMAP_WWORLD_H,WORLD_W

World struct的总大小至少为:WORLD_H * WORLD_W * (MAP_H * MAP_W * 2 * sizeof(Tile) + MAP_NAME_LEN)(加上编译器可能插入的任何填充)。

编辑

现在你已经添加了常量就可以计算出你的数据结构将消耗大约3.5MB(如果sizeof(Tile) == 4)。这对于堆栈来说太多了。默认堆栈大小通常约为1MB。使用malloc在堆上分配数据结构。

+0

呃?为什么tile的成员是32位对齐的? – bdonlan 2011-12-31 21:04:47

+0

@bdonlan许多体系结构都需要对齐内存访问权限,否则会导致惩罚。标准的编译器优化是在32位(在32位系统上)对齐struct结构成员 – ChrisWue 2011-12-31 21:09:50

+0

我从来没有见过编译器为'char's(这个'byte'可能是typedef)做的。并且机会是OP在x86上(因为他提到了Windows 7),而Windows x86 ABI没有对齐字符。 – bdonlan 2011-12-31 21:11:58

1

当你typedef一个结构,你有给出一个名字,语法是typedef struct foo { /* ... */ } Foo;(foo标签是可选的)。

编辑现在,随着大小,它很可能是堆栈溢出。 A Map仅使用4KB,因此World接近4MB。据我记忆,Windows只给你一个较小的堆栈(假设它是1MB?)。

+0

这不会导致崩溃。 – bdonlan 2011-12-31 21:05:29

+0

事实上,我将程序编译为C++,编译器不会抱怨任何事情,只是出于某种原因程序在创建World实例时崩溃。我会尝试减小数组的大小,看看它是否仍然崩溃,然后我会看看是否由于堆栈溢出。感谢您的建议! – 2011-12-31 21:12:30

+0

@bdonlan咦? OP的代码甚至不应该编译,更不用说运行了。如何使用没有名字的typedef?甚至是什么呢? – jlehr 2011-12-31 21:13:50

1

default stack size(与VS2010无论如何)是1MB。

sizeof(World) == 3921920,这比1MB大3倍以上。

您看到的崩溃是堆栈溢出。

您可以尝试增加堆栈大小(请参阅关于如何执行此操作的链接),或者在堆上分配World对象。

+0

事实上,我发现通过将WORLD_H和WORLD_W减少到23,程序运行良好。如果我增加这些值,那么堆栈溢出并且程序崩溃。所以我只需要分配一个更小的“世界”或像你说的那样,增加堆栈的大小或者将它分配到堆上。 – 2011-12-31 21:17:05