0

I want to declare an unsigned long long array with 2mil. elements. When I first define the length of the array const and then define the array I get a segmentation fault error. However when I define the length just as unsigned long long the declaration works.

int main(int argc, const char *argv[])
{
    const unsigned long long lim = 2000000; //If I omit const, it works.
    unsigned long long nums2lim[lim];

    exit(EXIT_SUCCESS);
}

Does anybody know why the segmentation fault is thrown?

bergercookie
  • 2,542
  • 1
  • 30
  • 38
  • 1
    This does not look like C++ – Eregrith May 04 '15 at 15:44
  • 5
    Your stack is most likely not big enough for 2 million unsigned long longs. – dwcanillas May 04 '15 at 15:45
  • 1
    Local variables, including arrays, are stored at the stack, and the stack is limited. On Windows the default stack is just a single megabyte, on Linux it's 8 MB. Your array is almost *sixteen* MB. – Some programmer dude May 04 '15 at 15:45
  • 1
    _"Does anybody know why the segmentation fault is thrown?"_ Most probably because 8*2000000 exceeds your available stack size. – πάντα ῥεῖ May 04 '15 at 15:45
  • 1
    Also, `exit` should probably be `return` instead. – Mr. Llama May 04 '15 at 15:46
  • If a long-long is 64-bits (8byte), then 2,000,000 of them is 16mega-bytes... on the stack. Hint: How big is your normal stack size? (on most machines, its about 1 or 2 megs) – abelenky May 04 '15 at 16:00
  • 2
    None of this explains why the declaration "works" (doesn't segfault) if the `const` qualifier is removed. That's interesting. What compiler are you using (gcc, Visual Studio, ...)? – John Bode May 04 '15 at 16:03
  • The compiler is gcc and it is running on OS X. – bergercookie May 04 '15 at 16:06
  • It *might* be because gcc treats the array as a constant length array if you declare `lim` as `const`, and variable length array if you don't. But I have no further evidence to back up this theory and this is only a wild guess. – user12205 May 04 '15 at 19:06
  • Related: C++ canonical Q&A answer that suggests new/delete or std::vector for the same problem: [Segmentation fault on large array sizes](https://stackoverflow.com/q/1847789) – Peter Cordes Nov 05 '21 at 04:23

3 Answers3

3

The auto memory (used in local arrays) has a limit well below the allocatable memory.

You can do practically the same with this (it uses pointers)

#include <stdlib.h>

int main(int argc, const char *argv[])
{
    unsigned long long lim = 2000000;
    unsigned long long *nums2lim=malloc(lim*sizeof(unsigned long long));

    free(nums2lim); // don't forget this!

    return EXIT_SUCCESS;
}
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
ForceBru
  • 43,482
  • 10
  • 63
  • 98
1

I have not been able to reproduce this behavior on my SLES 10 box (gcc 4.1.2, yes it's old). I get a segfault regardless of how lim is declared.

I'm going to go way, way, way, way out on a very skinny limb and point out that your definition of main is incorrect; argv should not be declared const (the standard mandates that the strings pointed to by the argv array should be modifiable). That bit of undefined behavior might be enough to cause the difference, but I seriously doubt it.

Either way, attempting to allocate 2 million anything in an auto array (VLA or not) is almost always bad juju. Maybe when computer memory is regularly measured in terabytes it won't be a problem anymore, but for now it's going to be bigger than the runtime stack is usually prepared to handle.

You have a few options available. One, you can declare the array with static storage duration, either by declaring it at file scope (outside of any function) or with the static keyword. Note this means you will not be able to use the lim variable to specify the size (even though you declare it const, lim is not a constant expression; its value is not known at compile time):

int main( int argc, char **argv )
{
  static unsigned long long nums2lim[2000000];
  ...
}

Alternately, you can allocate it from the heap at runtime:

int main( int argc, char **argv )
{
  const unsigned long long lim=2000000;
  int *nums2lim = malloc( sizeof *nums2lim * lim );
  if ( nums2lim )
  {
    ...
  }
  ...
}
John Bode
  • 119,563
  • 19
  • 122
  • 198
0

You would do this in C++ to allocate data in the heap:

const unsigned long long lim = 2000000;
unsigned long long *nums2lim = new unsigned long long[lim];
...
delete [] nums2lim;
ChronoTrigger
  • 8,459
  • 1
  • 36
  • 57