2011-12-31 53 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