C程序在分配复合结构时崩溃

C程序在分配复合结构时崩溃,c,struct,C,Struct,操作系统:Windows 7,编译器:GCC 3.2.3(MinGW) 我用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 t

操作系统:Windows 7,编译器:GCC 3.2.3(MinGW)

我用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说程序已经崩溃,正在寻找解决方案,等等)。你们知道为什么会这样吗


谢谢

我的最佳猜测是您的
World
对象超出了最大堆栈大小。这取决于您如何定义
MAP\u NAME\u LEN
MAP\u H
MAP\u W
WORLD\u H
WORLD\u W

World
结构的总大小至少为:
World\u H*World\u W*(MAP\u H*MAP\u W*2*sizeof(Tile)+MAP\u NAME\u LEN)
(加上编译器可能插入的任何填充)

编辑


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

根据
MAP\u NAME\u LEN
MAP\u H
MAP\u W
WORLD\u H
WORLD\u W
的值,您可能已经在堆栈上创建了一个大型结构。不要那样做。堆栈相对较小,通常不能处理总计超过几兆字节的分配(并且一次通常只能处理几十千字节的分配)。给定常量值,您可能会遇到这些限制-您的
世界
结构几乎有4MB大,太大了,无法合理地放在堆栈上

因此,请使用
malloc
将其分配到堆上,或者作为全局或文件局部静态变量:

World world;

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


当您
typedef
a struct时,您必须给出一个名称,语法是
typedef struct foo{/*…*/}foo(foo标记是可选的)

编辑现在,根据大小,很可能是堆栈溢出。
Map
仅使用了4KB,因此
World
接近4MB。据我记忆所及,Windows只提供了一个较小的堆栈(我认为是1MB?)。

该堆栈(无论如何,VS2010)是1MB

sizeof(World)=3921920
,比1MB大3倍多

您看到的崩溃是堆栈溢出


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

请发布
MAP\u NAME\u LEN
MAP\u H
MAP\u W
World\u H
World\u W
的值。可能是堆栈溢出。映射W/H WORLD W/H的定义是什么?也许你在堆栈上放的太多了?你在使用typedef时没有声明定义。您应该这样写:typedef struct\u Map{…}Map;你也可以省略_映射,创建匿名结构,如果你喜欢的话。嗯?为什么磁贴的成员是32位对齐的?@bdonlan许多体系结构需要对齐的内存访问,否则将受到惩罚。标准的编译器优化是在32位(在32位系统上)上对齐结构成员。我从未见过编译器对
char
s(这可能是
byte
的typedef)这样做。很可能OP是在x86上的(因为他提到了Windows 7),而Windows x86 ABI不对齐字符。@bdonlan Mh,没错-当你开始混合较大的类型时,如
int
,填充通常会出现。我删除了这个部分,这不会导致崩溃。事实上,我正在编译程序C++,编译器不会抱怨任何事情,只是因为某些原因,程序在创建World实例时崩溃。我将尝试减少数组的大小,看看它是否仍然崩溃,然后再看看是否是由于堆栈溢出。谢谢你的建议@波顿兰,嗯?OP的代码甚至不应该编译,更不用说运行了。如何使用没有名称的typedef?如果这是在C++代码库中,你可能想在你的问题中指出这个问题。@ JLHR,未命名的Type是可以接受的,至少在GCC中是这样的:这是毫无意义的,但是它并不是导致OP程序在运行时崩溃,所以这不是回答问题。我刚刚发现,通过将WORLD_H和WORLD_W都减少到23,程序运行良好。如果我增加这些值,那么堆栈溢出,程序崩溃。所以我只需要分配一个更小的“世界”,或者像你说的,增加堆栈的大小或者在堆上分配它。
int main()
{
    World *world = malloc(sizeof(*world));
    /* ... */
    free(world);
}