• Advertisement
Sign in to follow this  

Pre-Main() stack-overflow with SDL

This topic is 4710 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

A'right. What the hell just happened? A minute ago everything was all right on my shiny, well-progressing SDL project. Suddenly, even before the first line of code in the main() scope, I get an 'illegal action' windows thingy. If i try to debug the project, it says that I have a stack overflow. I tried tracing back and returning to the state when everything worked fine, and the problem still occurs. I tried that on two different computers, with VS6 and VS2003\VC++ 2003. I can't find the source of the problem, and I don't even understand where does the stack overflow comes from. Can somebody please help me? :(

Share this post


Link to post
Share on other sites
Advertisement
It probably happens in the constructor of a global variable, since they are called before the main function is called. It might be in one of the sdl libraries, but I doubt that, it's most likely in one of your own global variables, so check them.

Share this post


Link to post
Share on other sites
Are you using global variables? Are those variables classes, and do you call recursive functions during construction, or are you "just" creating a huge number of objects?

Share this post


Link to post
Share on other sites
Here is the code of the whole main.cpp file.

#include <SDL.h>
//#include "InfoBlock.h"
#include "GameCore.h"

//#include "Art//font.h"


int main(int argc, char *argv[])
{
SDL_Event event;

/*InfoBlock *info = new InfoBlock;

info->SetResolutionParamaters(640,480,24);
info->SetMapRect(0,640,0,480);
info->SetControlsRect(0,0,0,0);
info->SetTileSize(16);
info->SetMapSize(100,100);
info->SetFLTile( 1 << 0 , 19 << 0 );

delete info;*/


GameCore GameEngine;



GameEngine.LoadDatFile("Art\\maptiles.dat");

GameEngine.LoadMap();

if( GameEngine.SetVisibleArea(0,2, true) == 0)
{
printf("Error setting visible area.");
exit(0);
}

/* // ****

GameEngine.LoadDatFile("Art\\font.dat");

KrFontResource *font = GameEngine.engine->Vault()->GetFontResource("CONSOLE");

KrTextBox *text = new KrTextBox(font, 160, 15, 2);

GameEngine.engine->Tree()->AddNode(0,text);

text->SetPos(480,450);
text->SetVisible(true);

text->SetTextChar("Charlie. - v0.4 Beta :)",0);

// ****** */


GameEngine.Draw();

SDL_Delay(1000);

SDL_PollEvent(&event);
do
{
while(event.type!=SDL_KEYDOWN && event.type!=SDL_MOUSEMOTION)
SDL_PollEvent(&event);

GameEngine.ScrollMap(&event);
GameEngine.Draw();

event.type = 0;
}while(event.key.keysym.sym != SDLK_ESCAPE);

SDL_Delay(1000);

return 1;
}


FYI, everything in the main used to work until suddenly the god of war bumped into my pc, so don't try to search for the errors inside the scope. The overflow even hints it's outside of it.

Share this post


Link to post
Share on other sites
There aren't any globals in this file. Is this the only file of your project? If not, you should look in the other files for global variables, try to remark them out, and see if you still get the error.

Share this post


Link to post
Share on other sites
And then I sat there, wondering: "Jeez, I think they would also like to see what the hell 'GameCore.h' is?"

#ifndef __GAMECORE_H
#define __GAMECORE_H

#pragma comment(lib, "sdl.lib")
#pragma comment(lib, "sdlmain.lib")
#pragma comment(lib, "sdl_image.lib")
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "engine.lib")

#pragma warning( disable : 4530 )
#pragma warning( disable : 4786 )

#include <stdlib.h>
#include <string>
#include <windows.h>
#include <iostream>
#include <fstream>
#include <SDL.h>
#include <engine/kyra.h>

#include "MapTile.h"
#include "General.h"
//#include "InfoBlock.h"

// Art *.dat files:

#include "art\\maptiles.h"

// ******

using namespace std;

const int ResolutionX = 640;
const int ResolutionY = 480;
const int ResolutionBPP = 24; // Bits per pixel (color depth).

const int Screen_Map_Rect_X1 = 0;
const int Screen_Map_Rect_X2 = 640;
const int Screen_Map_Rect_Y1 = 0;
const int Screen_Map_Rect_Y2 = 480;

const int Screen_Controls_Rect_X1 = 0;
const int Screen_Controls_Rect_X2 = 640;
const int Screen_Controls_Rect_Y1 = 336;
const int Screen_Controls_Rect_Y2 = 480;

const int TileSize = 16; // Tiles have (x,x) size (Simetrical square).

const int Map_Size_X = 100;
const int Map_Size_Y = 100;

const int Visible_Map_Size_X = Map_Size_X / TileSize;
const int Visible_Map_Size_Y = Map_Size_Y / TileSize;

const U32 FirstTile = MapTile_Grass;
const U32 LastTile = MapTile_Forest_North_West;

enum TerrainType { M,F };
enum ScrollDirection { North, NorthEast, East, SouthEast,
South, SouthWest, West, NorthWest };


class GameCore // Master-class for handling and executing the major graphic and gameplay parts of the project's code.
{
public:

// Variables:

MapTile *Map[2000][2000]; // The map tiles array.

MapTile *VisibleMap[300][300];



// Functions:

GameCore(); // Constructor();

~GameCore(); // ~ Destructor :]


// Graphic Functions:

void LoadDatFile(const char *dat_filename); // Loads an image (Sprite, tile, etc.) resource to the engine's vault.

KrSpriteResource *GetKrSpriteResource(U32 Resource); // Fetches a sprite resource from the *.dat file.
KrTileResource *GetKrTileResource(U32 Resource); // Fetches a sprite resource from the *.dat file.

KrSprite *GetKrSprite(KrSpriteResource *Resource); // Creates a ready-to-use sprite variable.
KrTile *GetKrTile(KrTileResource *Resource); // Creates a ready-to-use tile variable.

// ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
// *** Make sure to #include the header file (*.h) of the sprite at the head of the page! ***
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

// Map handling functions:

void LoadMap(); // Loads the map to the MapTile 'Map' buffer.
void Draw(); // Draws everything to the screen (Graphic execution procedure).
void ScrollMap(SDL_Event *event); // Scrolls the map according to the given movement event.
int SetVisibleArea(int x, int y, bool firsttime); // firsttime = false


private:
// Variables:

SDL_Surface *screen; // the surface to be drawn into. This is handled by the Kyra (tm) engine.

KrEngine *engine; // Our beloved, almighty engine :) This is the core of the graphics stuff.


// Importnant graphic and in-game handling paramaters:

/*int ResolutionX; // Resolution of the screen.
int ResolutionY;
int ResolutionBPP; // Bits per pixel (color depth).

int Screen_Map_Rect_X1; // X,Y paramaters for the map part of the screen.
int Screen_Map_Rect_X2;
int Screen_Map_Rect_Y1;
int Screen_Map_Rect_Y2;

int Screen_Controls_Rect_X1; // X,Y paramaters for the controls part of the screen.
int Screen_Controls_Rect_X2;
int Screen_Controls_Rect_Y1;
int Screen_Controls_Rect_Y2;

int TileSize; // Tiles have (x,x) size (Simetrical square).

int Map_Size_X; // Size of the map, in tiles.
int Map_Size_Y;

int Visible_Map_Size_X; // The actual amount of tiles seen on the screen, since the..
int Visible_Map_Size_Y; // .. original map is too large to be blitted all at once.

U32 FirstTile; // Map handling paramater.
U32 LastTile; // Map handling paramater.*/




// Functions:

// Screen initialization functions:

void Init_SDL_Port(); // Returns a ready-to-use SDL_Surface pointer.


// Map initialization functions:

U32 DecideTerrain(int x, int y, TerrainType type); // Returns the tile need to be drawn at a specific coordinate (in U32 form).


// Map handling functions:

void ScrollNorth();
void ScrollWest();
void ScrollEast();
void ScrollSouth();

bool AnyTerrain(int x, int y, TerrainType type);

bool NorthWest(int x, int y, TerrainType type);
bool North(int x, int y, TerrainType type);
bool NorthEast(int x, int y, TerrainType type);
bool East(int x, int y, TerrainType type);
bool SouthEast(int x, int y, TerrainType type);
bool South(int x, int y, TerrainType type);
bool SouthWest(int x, int y, TerrainType type);
bool West(int x, int y, TerrainType type);
bool Center(int x, int y, TerrainType type);

};

#endif




General.h and MapTile.h aren't the problem. They haven't been touched for over a month, so they're not the problem.

Also, could someone please explain to me what are those 'pragma' stuff? Someone told me to put them there just cause it helps to make stuff work. I would also like to know how does it make stuff work. Thanks! :)

Share this post


Link to post
Share on other sites


MapTile *Map[2000][2000]; // The map tiles array.

MapTile *VisibleMap[300][300];

it's these lines. Those arrays will both be created on the stack, but they are way too big for that.
2000 * 2000 * sizeof(Map*) = 16MB, while the stack is only 1 MB by default. You will have to allocate the memory with new or use a std::vector or so.

Share this post


Link to post
Share on other sites
#pragma comment (lib, file) tells the compiler to include certain libraries.
#pragma warning (disable, nr) tells the compiler not to show certain warnings.

More information can be found here

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Your Map array alone is about 16MB big, that's definitely to big for the stack. You should use new[]/delete[] to put on the heap.
And those #pragma's are sepcial compiler options.
#pragma comment(lib, "sdl.lib" ) i.e. tells VC++ to link your program with sdl.lib.

Share this post


Link to post
Share on other sites
MapTile *Map[2000][2000]; // The map tiles array.

MapTile *VisibleMap[300][300];

Are you sure you need a 3 dimensional array?

Share this post


Link to post
Share on other sites
Quote:
Original post by DerAnged
MapTile *Map[2000][2000]; // The map tiles array.

MapTile *VisibleMap[300][300];

Are you sure you need a 3 dimensional array?


3D? I only see 2

Share this post


Link to post
Share on other sites
Quote:
Original post by quasar3d
Quote:
Original post by DerAnged
MapTile *Map[2000][2000]; // The map tiles array.

MapTile *VisibleMap[300][300];

Are you sure you need a 3 dimensional array?


3D? I only see 2


I am extremely tired, but right now i am under the assumtion that becasue the * is making it a pointer, it is a 3 dimensional array, in ways, ie:

char* name;
can be used to a point like
char name[255];

but then again i am seeing how i am totally wrong most likely, as that is not always the case.

Share this post


Link to post
Share on other sites
It works! It absoloutly works! Even my stupid old computer's teacher couldn't solve it! [wow]

Thanks! You all got my rating. :)

Now all I have left is to fix to prog and ask these following questions:

1. How did you know that the size of the array is exactly 16MB?
2. How did you know if I do it pointer-less it goes straight into the stack (for temporary use)?
3. Is there a way to incerse the stack's size?

PLease explaing my mistakes, I would like to know from them! :)

You have my thanks again, oh gurus of great computer wisdom.

Here's a treat for your help - one of the funniest net-flash-toons ever made: http://www.illwillpress.com/vault.html

Share this post


Link to post
Share on other sites
Quote:
Original post by Twiggy
It works! It absoloutly works! Even my stupid old computer's teacher couldn't solve it! [wow]

Thanks! You all got my rating. :)

Now all I have left is to fix to prog and ask these following questions:

1. How did you know that the size of the array is exactly 16MB?
2. How did you know if I do it pointer-less it goes straight into the stack (for temporary use)?
3. Is there a way to incerse the stack's size?

PLease explaing my mistakes, I would like to know from them! :)

You have my thanks again, oh gurus of great computer wisdom.

Here's a treat for your help - one of the funniest net-flash-toons ever made: http://www.illwillpress.com/vault.html


2000 * 2000 * 4 /1000000 = 16.

Share this post


Link to post
Share on other sites
Why do you multiply it with 4/100000 ?

The reason I set it to 2000x2000, was because I couldn't determine the size needed for the map before I executed the main project, so I just gave it a big size so that almost every 'map size' that i will want to use will be smaller than that and fit right in the array.

So, how can I determine the size of an inside-class two-dimensoinal array?

I mean, how can I solve the problem?

Share this post


Link to post
Share on other sites
The 1,000,000 presumably stems from the fact that 1,000,000 bytes is roughly 1 MB (actually, 1 "MiB" is 1024*1024=1,048,576 bytes).

Share this post


Link to post
Share on other sites
Quote:
Original post by Miserable
The 1,000,000 presumably stems from the fact that 1,000,000 bytes is roughly 1 MB (actually, 1 "MiB" is 1024*1024=1,048,576 bytes).


That's the ticket, i kept wanting to say bits.

Share this post


Link to post
Share on other sites
Quote:
Original post by Twiggy
1. How did you know that the size of the array is exactly 16MB?
2. How did you know if I do it pointer-less it goes straight into the stack (for temporary use)?
3. Is there a way to incerse the stack's size?

1) 2000 elements * 2000 elements = 4000000 elements. Each element is 4 bytes (size of a pointer on a 32-bit OS/compiler is 4 bytes), so that's 16000000 bytes. There are roughtly 1000000 bytes in a Mb, so that's 16Mb (Actually, as others have said, there's 1048576 bytes in a Mb, so the array is 15.26Mb)

2) That's just the way it works. If it's not allocated with new[] or new, then it goes on the stack

3) Yes, but you *really* shouldn't need to. It's a compiler option. For VC 2003, it's in project settings -> Linker -> System -> Stack Reserve Size, and set it to whatever you like.
The default is 1Mb in MSVC, I don't know about other compilers.

Share this post


Link to post
Share on other sites
Thanks! :)

Again -> So how can I determine the size of the arrays before run-time?

Share this post


Link to post
Share on other sites
Quote:
Original post by Twiggy
Thanks! :)

Again -> So how can I determine the size of the arrays before run-time?


multiply together all of the sizes.
multiply that by sizeof(type);
divide that by 1048576

Share this post


Link to post
Share on other sites
But, dude, I can't create a MapTile *Map[][] inside the class. I have to determine it sizes, which is changeable. It should be Map_Size_X and Map_Size_Y
But i'm gonna change the class so that the Map_Size_X and Map_Size_Y can be changed by the programmer. <I'm creating it to be distributed to other folks>

^----Unlike in the block of code of GameCore.h above (I changed it)

Share this post


Link to post
Share on other sites
Quote:
Original post by Twiggy
But, dude, I can't create a MapTile *Map[][] inside the class. I have to determine it sizes, which is changeable. It should be Map_Size_X and Map_Size_Y
But i'm gonna change the class so that the Map_Size_X and Map_Size_Y can be changed by the programmer. <I'm creating it to be distributed to other folks>

^----Unlike in the block of code of GameCore.h above (I changed it)


Simple, in your class declare a double pointer and allocate some dynamic memory in the constructor of the class. I've never really worked with 2D arrays or such, but I believe you would declare

MapTile **Map;

in your class, and in your constructor just say

*Map = new MapTile[foo];
Map = new MapTile[bar];

then just delete the memory in the destructor. That'd work right? Again, not my area of expertise.

Share this post


Link to post
Share on other sites
You can create MapTile ***Map, but this is nasty. (A two-dimensional array of pointers.)
First you do Map = new MapTile**[Map_Size_X], and then you need to go through all elements and do Map[idx] = new MapTile[Map_Size_Y]. (Idx is a counter which goes from 0 to Map_Size_X - 1)

When you delete the Map array, you need to delete in reverse order. First: delete[] Map[idx] and then delete[] Map. Probably you need to call delete on the Map objects first.

IMHO it's better to use a vector. You can create a two-dimensional vector this way: vector<vector<MapTile *>> Map. Use reserve or the vector constructor to allocate space. You still need to loop through the "inner" arrays. Also, don't forget to delete the Map objects when you're done.

If anyone knows a way to handle this more efficiently, I'd be interested too.

Share this post


Link to post
Share on other sites
Why would you want to find out map size before run time? you can store map size in the header of the map file (ie. first two numbers are map sizes the rest are tile data) and then at run time make enough room to hold all your map data, no matter how big they are :)

you can do it using vectors as suggested, or:

// define it like this
MapTile **map;
...

// create a new, custom sized map on the heap ...
*map = new MapTile[ map_size_x ];
for( int x=0; x<map_size_x; x++ )
map[x]=new MapTile[ map_size_y ];

// access it as usual with
map[x][y] = ...

// delete it properly..
for( int x=0; x<map_size_x; x++ )
delete [] map[x];



hope this helps! if not, i'll try to explain more..

edit: forgot how to use code tags, need to post more often ;)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement