2

I'm converting a program from fortran to C++.

My code seems to run fine until I add this array declaration:

 float TC[100][100][100];

And then when I run it I get a segmentation fault error. This array should only take up 8Mb of memory and my machine has 3 Gb. Is there a problem with this declaration? My c++ is pretty rusty.

  • 1
    Segmentation fault usually occurs when you try to access memory you are not allowed to. Are you sure you are not accessing past the limits of you array? – lvella Nov 11 '11 at 19:33
  • That array actually requires a little less than 4 MB of space. – David Alber Nov 11 '11 at 19:40

5 Answers5

3

I'm guessing TC is being allocated as an auto local variable. This means it's being stored on the stack. You don't get 4mb of stack memory, so it's causing a stack overflow.

To solve it, use dynamic allocation with a structured container or new.

tenfour
  • 36,141
  • 15
  • 83
  • 142
  • Thanks for your help! I didn't have to deal with any of that stuff in Fortran, so I'm a little ignorant about it. – user1042343 Nov 16 '11 at 17:17
3

That array is about 4 megabyte large. If this definition is inside a function (as local variable), then the compiler tries to store it on the stack, which on most systems cannot grow that large.

The Fortran compiler probably allocated it statically (Fortran routines are not allowed to be called recursively unless explicitly marked as recursive, so static allocation for local variables works there for non-recursive functions), and therefore the error doesn't occur there.

A simple fix would be to explicitly declare the variable static, assuming the Fortran function was not declared recursive. However this may bite you later, if you ever try to call that function recursively from a revised version. So a better solution would probably be to allocate it dynamically. However that costs extra time and therefore depending on the nature of the code, may hurt your performance too much (Fortran code quite often is numerical code where performance matters).

If you choose to make the array static, you can build in a protection against accidental recursive calls:

void yourfunction()
{
  static bool active;
  static float TC[100][100][100];

  assert(!active);
  active = true;

  // your code

  active = false;
}
celtschk
  • 19,311
  • 3
  • 39
  • 64
0

This looks like a stack-based declaration. Try allocating from the heap (i.e. using the new operator).

Throwback1986
  • 5,887
  • 1
  • 30
  • 22
0

If you are declaring it inside of a function, as a local variable, it may be that you stack is not big enough to fit the array. You may try to allocate in the heap, with new or malloc(), or, if your design allows, make it a global variable.

lvella
  • 12,754
  • 11
  • 54
  • 106
0

In C++ the stack has a limited amount of space. MSVC defaults this size to 1MB. If the stack uses more than 1MB it will segfault or stackoverflow or something. You will have to move that structure to dynamic memory. To move it to dynamic memory, you want something like this:

typedef float (bigarray)[100][100][100];
bigarray& TC() {
    static bigarray* ptr = NULL;
    if (ptr == NULL) {
        ptr = new float[100][100][100];
        for(int j=0; j<100; j++) {
            ptr[j] = new float[100][100];
            for(int i=0; i<100; i++)
                ptr[j][i] = new float[100];
        }
    }
    return *ptr;
}

That will allocate the structure in dynamic memory the first time it is accessed, as a jagged array. You can get more performance out of a rectangle array, but you have to change types:

typedef std::vector<std::array<std::array<float, 100>, 100> bigarray;
bigarray TC(100);

According to http://cs.nyu.edu/exact/core/doc/stackOverflow.txt, gcc/linux defaults the stack size to 8MB, which isn't big enough for your structure and int main() If you really want to, MSVC has flags to increase the stack sizes up to 32MB. Linux has a ulimit command to increase the stack size up to 32MB.

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158