2

So, I'm working at inventing my own tile map creation and I got a problem on size. The maximum size (which I did not set) is <700x700, anything higher makes it crash. First, I thought it's something I got wrong when making the "presentation version" which outputs the result on screen -> ScreenShot, but now I just finished making it more compact and tried using 800x800 and it still has the 7 limit, but I have no idea why. Since the code isn't that big I will show it here. If you have some tips I don't mind taking them.

#include <iostream>
#include <string.h>
#include <fstream>
#include <ctime>
#include <cstdlib>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#define _WIN32_WINNT 0x0501
#include <windows.h>
using namespace std;

int main()
{

  sf::Vector2i Size;
  int Points,rands,PointsCheck=1,x,y,RandX,RandY,CurrentNumber=1;
  srand(time(0));
  bool Done=false,Expanded,Border;
  ofstream Out("txt.txt");
  /***/
  cout << "Size X-Y = "; cin >> Size.x >> Size.y;cout << endl;
  cout << "MAX Points - " << (Size.x*Size.y)/10 << endl;
  cout << "Number of POINTS = ";cin >> Points ;cout << endl;
  /***/
  int PixelMap[Size.x+1][Size.y+1];
  /***/
  for (x=1;x<=Size.x;x++) for (y=1;y<=Size.y;y++) PixelMap[x][y]=0;
  /***/
  while(PointsCheck<=Points)
    {
     rands=1+(rand()%10);
     RandX=1+(rand()%(Size.x));RandY=1+(rand()%(Size.y));
     if (rands==1 && PointsCheck<=Points && PixelMap[RandX][RandY]==0)
     {PixelMap[RandX][RandY]=CurrentNumber;CurrentNumber+=2;PointsCheck++;}
    }
  /***/
  while(Done==false)
   {
    Done=true;
    for(x=1;x<=Size.x;x++)
     for(y=1;y<=Size.y;y++)
      if(PixelMap[x][y]%2!=0 && PixelMap[x][y]!=-1)
       {
        if (PixelMap[x+1][y]==0) PixelMap[x+1][y]=PixelMap[x][y]+1;
        if (PixelMap[x-1][y]==0) PixelMap[x-1][y]=PixelMap[x][y]+1;
        if (PixelMap[x][y+1]==0) PixelMap[x][y+1]=PixelMap[x][y]+1;
        if (PixelMap[x][y-1]==0) PixelMap[x][y-1]=PixelMap[x][y]+1;
       }
    for(x=1;x<=Size.x;x++)
     for(y=1;y<=Size.y;y++)
      if(PixelMap[x][y]!=0 && PixelMap[x][y]%2==0) {PixelMap[x][y]--;Done=false;}
   }
   for(x=1;x<=Size.x;x++){
    for(y=1;y<=Size.y;y++)
     {Out << PixelMap[x][y] <<  " ";}Out << endl;}

   //ShowWindow (GetConsoleWindow(), SW_HIDE);
}
  • When it crashes, what type of error are you seeing? Are you running out of memory? Segmentation fault? – AndyG Aug 15 '13 at 01:58
  • Just a plain oll crash . The program starts , i write the numbers and it goes white saying it's not responding anymore. – Eilers William Aug 15 '13 at 02:08
  • This looked like a stack overflow candidate, but I think it's array out-of-bounds access instead. See my comment below my answer. – paddy Aug 15 '13 at 02:14
  • I understand but if it's array out-of-bounds access , then why is it working for values beneath <700, get my drift? And I only set int PixelMap[Size.x+1][Size.y+1]; (Size.x+1) so when I write my for I can start from 1 and go till <=Size.x since otherwhise I would have to go from 0 to – Eilers William Aug 15 '13 at 02:35

3 Answers3

0

What you have here is the concept from which this site gets its name. You have a stack overflow:

int PixelMap[Size.x+1][Size.y+1];

If you want to allocate a large amount of memory, you need to do it dynamically (on the heap).

You can do this any number of ways. Since you are using C++, I recommend using a std::vector. The only trick is making the array 2-dimensional. Usually this is done in the same way as the one you allocated on the stack, except you don't get language syntax to help you:

vector<int> PixelMap( (Size.x+1) * (Size.y+1) );

Above, you'll need to calculate the linear index from the row/column. Something like:

int someval = PixelMap[ row * (size.y+1) + column ];

If you really want to use the [row][column] indexing syntax, you can either make a vector-of-vectors (not recommended), or you can index your rows:

vector<int> PixelMapData( (Size.x+1) * (Size.y+1) );
vector<int*> PixelMap( Size.x+1 );
PixelMap[0] = &PixelMapData[0];

for( int i = 0; i < Size.x+1; i++ ) {
    PixelMap[i+1] = PixelMap[i] + Size.y + 1;
}

Now you can index in 2D:

int someval = PixelMap[row][col];
paddy
  • 60,864
  • 6
  • 61
  • 103
  • Thanks for answering , though I don't know what you're talking about with a bit of google I'll learn something new and I'm sure my problem will get fixed in no time . Thanks ^^ , have a good day/night! – Eilers William Aug 15 '13 at 02:03
  • You know, after writing this, I've noticed something else. You might not have a stack overflow. Your loops are always `<=`, but inside those loops you index values at `x+1` or `y+1`. This can potentially index a value outside your array. If you want to do that without bounds checking, you'll need to make the array size `(Size.x+2) * (Size.y+2)`... or you could use `<` instead of `<=`. Depends which is correct for your program. – paddy Aug 15 '13 at 02:13
0

There's a couple of problems with your code:

First off:

int PixelMap[Size.x+1][Size.y+1];

 for (x=1;x<=Size.x;x++)
    for (y=1;y<=Size.y;y++)
         PixelMap[x][y]=0;

In the above snipped you are never setting the value of PixelMap[0][0], or PixelMap0, etc. Basically those values will be undefined. Arrays in C++ are 0 indexed so you need to be sure you address those. Also, why are you using Size.x+1 and Size.y+1? Something feels wrong about that.

A better loop would be:

int PixelMap[Size.x][Size.y];
     for (x=0;x<Size.x;x++)
        for (y=0;y<Size.y;y++)
             PixelMap[x][y]=0;

Second, this next bit of code is illegible:

while(PointsCheck<=Points)
{
     rands=1+(rand()%10);
     RandX=1+(rand()%(Size.x));
     RandY=1+(rand()%(Size.y));
     if (rands==1 && PointsCheck<=Points && PixelMap[RandX][RandY]==0)
     {
       PixelMap[RandX][RandY]=CurrentNumber;
       CurrentNumber+=2;
       PointsCheck++;
     }
}

You're only incrementing PointsCheck if

PointsCheck <= Points

Why? You test for this to be true in your while condition. PointsCheck doesn't get incremented anywhere before this test.

rands is never guaranteed to be equal to 1 by the way, so your loop could go on for eternity (though unlikely).

The next loop suffers from similar problems as above:

while(Done==false)
   {
    Done=true;

What's the reason for this? You never break out of the while loop, and you never set Done to false, so the next block of code will only ever be executed once. remove this bit.

Your for-loops that follow should start at 0 and go while < Size(Size.x and Size.y)

for(x=0;x<Size.x;x++)
     for(y=0;y<Size.y;y++)

Fix these issues first, and then if you still have a problem we can move on. And for all our sake, please use brackets {} to scope your for loops and if statements so that we can follow. Also, separate commands onto separate lines. It's a lot of work for us to follow more than one semicolon per line.

EDIT

Since you seem unwilling to fix these issues first: This could be an issue with the amount of memory allocated on the stack for your program. If you're trying to create an array of 800x800 integers, then you're using 800*800*4 bytes = 2.4 MB of data. I know this is higher than visual studio's default limit of 1 MB, but since a 700x700 array uses 1.8 MB, then whatever program you're using has a higher default (or you set visual studio's higher, but not high enough).

See if you can set your limit to at least 3 MB. More is better, though. If this doesn't fix your scaling problem up to 800, then you have other issues.

EDIT2

I just noticed this:

 sf::Vector2i Size;
  //unimportant stuff
  cin >> Size.x >> Size.y;
  int PixelMap[Size.x+1][Size.y+1];

Vector2i will probably have default values for x and y. If you want to dynamically allocate more than what those are, you cannot statically say

PixelMap[Size.x][Size.y]

You need to dynamically allocate the array. I strongly suggest using something like a std::vector > for this

e.g.(untested code):

  sf::Vector2i Size;
  //unimportant stuff
  cin >> Size.x >> Size.y;
  std::vector<vector<int> > PixelMap;
  //Initialize values to 0
  for(size_t i=0; i < Size.x; ++i){
     vector<int> nextVec;
     for(size_t j=0; j < Size.y; ++j){
        nextVec.push_back(0);
      }
      PixelMap.push_back(nextVec);
  }
AndyG
  • 39,700
  • 8
  • 109
  • 143
  • Hey thanks for answering me but I regret to inform you that my code DOES work will yet still to be found problem .The thing I'm trying to improve it's its scale. The first box: yes , I don't set them because I don't use them . I prefer writhing how I did than your following example because that's what I learned in class and used since then , sorry if it buggs you. Second : not sure what you're trying to say but it works as intented by me. The done parts gets set with done first and then in the following line set to false so it will run again if needed. And sorry for the {} .its how my class do – Eilers William Aug 15 '13 at 02:48
  • @EilersWilliam: Sometimes the way we're taught in class is not the best way ;) – AndyG Aug 15 '13 at 02:49
  • @EilersWilliam: See if you can increase the amount of stack memory allocated to your program. If you're using Visual Studio you can go to Properties -> Configuration Properties -> Linker -> System -> Stack Reserve Size – AndyG Aug 15 '13 at 02:52
  • I saw , but to use it I have to first learn what you used , so I can't respond right away . And i tried to increase the memory but I couldn't find where , niether with a search on google . (Codeblocks). – Eilers William Aug 15 '13 at 03:22
0

Not sure if this has anything to do with your crash (I would have added a comment, but I don't have the reputation), but here's a problem I noticed:

Your array indexing scheme is not consistent. Since you're using index 1 to indicate the first element, your bounds checking should look like this...

if (y!=1 && y!=Size.y && x!=1 && x!=Size.x && ...

...instead of this...

if (y!=0 && y!=Size.y && x!=0 && x!=Size.x && ...

[EDIT]

I just tried this:

...
cout << "asdf" << endl;
int PixelMap[Size.x+1][Size.y+1];
cout << "asdf" << endl;
...

and verified it's a stack overflow problem. So, as others mentioned above, allocate your pixel map on the heap and it should be fine.

BTW, this code...

int PixelMap[Size.x+1][Size.y+1];

is not standard C++. It's an extension some compilers provide, called 'variable length arrays'. Check this out for more info -> Why aren't variable-length arrays part of the C++ standard?

[/EDIT]

Community
  • 1
  • 1
d0c
  • 515
  • 5
  • 7
  • Thanks for answering . I'll try to fix the problem all mentioned . But the first thing it's my mistake , that shouldn't even be there T_T . It was copy-paste from another project and forgot to delete it . So sorry. – Eilers William Aug 15 '13 at 11:54