2

I am trying to generate a two-dimensional array of a struct, but this results in the program not launching. The window freezes and the program quits after a few seconds. Any idea why?

This is the file where I try to define the array cells.

#ifndef _FIELD_H_
    #define _FIELD_H_

class Field {
    public:
        static const int minX = -400;
        static const int maxX = 400;
        static const int minY = 0;
        static const int maxY = 400;

        Field();

    private:
        struct absCell {
            int material;
            float health;
        } cells[maxX - minX + 1][maxY - minY + 1];
};

#endif

The program is able to run when I remove these four lines:

        struct absCell {
            int material;
            float health;
        } cells[maxX - minX + 1][maxY - minY + 1];

Any idea how this happens? Any help is appreciated!

Update

Okay, apparently the problem is that this array gets quite big. Maybe you can help me to optimize this.

Material has to be an int between 0 and 10. Health has to be a float between 0 and 1 with a maximum of 2 fractional digits.

How can I limit the size of these vars?

Update 2

Mark B suggested the use of vectors while itwasntpete suggested the use of pointers, new and delete. Where is the difference, what are the advantages and disadvantages of these two methods? Thanks again!

Lars Ebert
  • 3,487
  • 2
  • 24
  • 46
  • Looks perfectly valid to me. Have you tried debugging it? The issue is most certainly somewhere else, not in the code you've shown us. – Violet Giraffe Sep 20 '13 at 18:24
  • 1
    There's nothing inherently wrong with that. The problem is probably elsewhere and it just happens to show up when you make that change. Try to create a SSCCE of the problem: http://sscce.org/ – Vaughn Cato Sep 20 '13 at 18:26
  • 5
    I'm going to dust off my aging and somewhat foggy crystal ball to suggest in `main()` you have something like `Field fld;` (worse, an *array* of `Field`. If so, note that this structure is defining a fixed stack-bound array of around 800x400 members, or 320000 `int` and `float` values. Assuming each is 4 bytes, thats 256000 bytes, or approximately **2.44 MB** of stack space *per Field object*. In short, I think it quite likely you're blowing out your stack. Please show us where you're *using* `Field`, specifically where-and-how the variables of type `Field` are defined. – WhozCraig Sep 20 '13 at 18:32
  • 1
    I estimate your class will need around 2.5 Gb of memory for each instance. That's not an impossibly big amount but it is quite a lot. Have you tried reducing the size of the array? – john Sep 20 '13 at 18:33
  • 1
    good example for a [stackoverflow](http://stackoverflow.com/). – user1810087 Sep 20 '13 at 18:38
  • I only need one instance of this class, but I can not reduce the size of the array. Maybe the size of the `struct` could be reduced? I need this array to store the status of a games environment. Could you tell me how to use the heap to store this? I have to store this data from the beginning of the program until the end. – Lars Ebert Sep 20 '13 at 18:58
  • How to use the heap? Just use vectors instead of an array, and use unsigned char instead of int and float (as Mark B says in his answer). – john Sep 20 '13 at 19:00
  • You say you cannot reduce the size of the array... Are you sure about that -- do you really have hundreds of thousands of unique values? If most of the values are the same or if they are somehow calculatable then there's no need to allocate a massive matrix -- a dictionary or some other sparse data structure would do fine. – Jussi Kukkonen Sep 20 '13 at 19:15
  • @jku The values are not calculatable and they are very likely to change constantly. There are about a thousand different values (Health 0 to 100 for about 10 different materials). How can I use another data structure than my array here? – Lars Ebert Sep 20 '13 at 19:20
  • what I mean is for example this: if most of the cells at any given time are of a default value, then you could store the non-default values in a dictionary (and use the default value if the cell is not in the dictionary). For your situation -- a game, lot of change in the cells -- this might not be applicable though. – Jussi Kukkonen Sep 20 '13 at 20:47
  • 2
    @LarsEbert Answer to update2, vectors are easier, pointers are very difficult for a newbie, as any amount of reading of this forum would tell you. – john Sep 21 '13 at 06:43

4 Answers4

4

You are allocating 801 * 401 (=321201) elements of struct absCell on the stack. Assuming you have a 32bit machine it is 2569608 Byte (~2.45 MB). According to this it is blowing up your stack.

Move the elements to heap like:

class Field {
public:
    static const int minX = -400;
    static const int maxX = 400;
    static const int minY = 0;
    static const int maxY = 400;

    Field() {
        cells = new absCell*[maxX - minX + 1];
        for(int i=0; i<maxX - minX + 1; i++)
            cells[i] = new absCell[maxY - minY + 1];
    }

    ~Field() {
        for(int i=0; i<maxX - minX + 1; i++)
            delete[] cells[i];

        delete[] cells;
    }

private:
    struct absCell {
        unsigned char material;
        unsigned char health;
    }**cells;
};

Update

Material and health can be saved in a char. Accessing health you have to recalculate it:

put -> x*100
get -> x/100

Update 2

Except you have some reasons, using a vector is most likely the better option, as Mark B 's answer describes.

user1810087
  • 5,146
  • 1
  • 41
  • 76
3

Based on update note:

The first thing you can do is easily optimize your struct for space by using unsigned char for each attribute, using a fixed-point representation for your existing float (for example 0.23 would be stored as the integer 23).

Then store the structs on the heap with vector instead of an array:

    struct absCell {
        unsigned char material;
        unsigned char health;
    };
    std::vector<std::vector<absCell> > cells_;

Then set up the constructor:

Field() : cells_(maxX - minX + 1, std::vector<absCell>(maxY - minY + 1)) {}
Mark B
  • 95,107
  • 10
  • 109
  • 188
2

My guess is you're hitting the stack limit. When you make that array like it is its trying to put 801*401*8 bytes on your stack. I did a quick compile and was having crashes until I lowered the numbers for your various mins and maxes.

Tamathar
  • 101
  • 3
2

If I got your snippet right way, you're trying to create an array. Allocation of the array is stack-based, with more than 2 Mb size required. There may be a chance that your stack has less than that 2Mb available, thus the code crashes right at the moment you're entering the function.

Try to allocate the same array dinamically.

Yury Schkatula
  • 5,291
  • 2
  • 18
  • 42