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