8

I was working on an assignment (details in another question). As part of it, I was increasing the size of the array. And found that when I try to initialize an array:

int arr[2097152]; // 8MB

I got segmentation fault ... I think its because I am trying to declare an array that too large? Then I found the way to get around this is to use malloc. But being new to C (mainly use JavaScript/Python/Java ...). I get very confused with pointers and stuff ...

I've declared an array 8MB:

int *arr = malloc (MBs * 1024 * 1024 / sizeof(int)); // MBs = 8

But now ... how do I access it, or write to it? When I use it like arr am I getting the address, and if I use *arr I get the 1st element?

Community
  • 1
  • 1
Jiew Meng
  • 84,767
  • 185
  • 495
  • 805
  • 1
    Coming from JS/Python you should learn the difference between stack and heap memory allocation. – Joe Sep 26 '12 at 09:38
  • `malloc` takes the number of bytes as its argument, so it's just `malloc(MBs * 1024 * 1024);`. – Kerrek SB Sep 26 '12 at 09:39
  • 1
    Apart from answers mentioning malloc and difference between stack and heap, keep in mind that you have to free this array yourself too. If you only created it once in your program, you might get away because it is automatically freed when your program terminates. However, it is a disaster if you do this allocation repeatedly in some function thinking the array is destroyed once you go out of scope – fkl Sep 26 '12 at 09:42

5 Answers5

11

Use it like arr[index], just as if it were declared as an array. In C, the notation x[y] is exactly equivalent to *(x + y). This works in the case of an array because the array name is converted to a pointer to its first element.

int *arr = malloc (MBs * 1024 * 1024 / sizeof(int));

This is not a good approach (and doesn't make it the size you want), because you don't have the number of elements handy. You should declare it based on the number of elements, e.g.,

#define ARR_LENGTH 2097152
int *arr = malloc (ARR_LENGTH * sizeof *arr);

You need to multiply by the element size because malloc's argument is a byte count.

Jim Balter
  • 16,163
  • 3
  • 43
  • 66
  • Why is it not a good approach? Is it because `MBs * 1024 * 1024 / sizeof(int)` might give a decimal or something? And I think u mean `sizeof(int)` instead? ... Oh, by "I dont have size of array", its because I cant do `sizeof(arr)/sizeof(int)` anymore to find the size of array? – Jiew Meng Sep 26 '12 at 09:56
  • 4
    @JiewMeng Yes, you can't do that, but you need to know the number of elements. And I meant what I wrote, `sizeof *arr`, which avoids dependency on the type. if you change the type later, your program has a bug and may crash randomly. If you change the variable name, you just get a syntax error. Believe me, I have 35 years experience with C, and this is best practice. – Jim Balter Sep 26 '12 at 10:00
  • 1
    @JiewMeng Another reason to use `sizeof *arr` is that it is always the same across all your malloc calls, while OTOH types can be complex or prone to typos, and getting it wrong can be a disaster. Suppose, e.g., you have an array of pointers to strings that you write as `char** arr = malloc(ARR_SIZE * sizeof(char))` ... oops, bug city, because you didn't allocate enough memory. – Jim Balter Sep 26 '12 at 10:40
5

I think its because I am trying to declare an array that too large?

Yes, Indeed. You are most likely doing this in a function. Wherein the array is created on local storage on stack and usually stack will not be big enough to cater to demands of this big size.
The usual solution is to use dynamic memory.

How do I access it, or write to it? When I use it like arr I am getting the address, and if I use *arr I get the 1st element?

You can access it in similar way as you use an array by using the [] operator.

Note that,

arr[i] == i[arr] == *(arr + i) == *(i + arr)

So,

arr[0] ---> Gives you first element
arr[1] ---> Gives you Second element
and so on...

Note that the name of the array decays as an pointer to its first element sometimes but arrays and pointers are not the same!

Good Read:

How do I use arrays in C++?

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
3

Yes, you can use it the same way as an ARRAY.

int *arr = malloc (MBs * 1024 * 1024) ;
arr[0] = 1 ;
arr[6] = 675 ;
etc. ;

*arr = arr[0] ; \First element

Abhineet
  • 5,320
  • 1
  • 25
  • 43
2

The notation a[i] is identical to *(a + i) (and thus also to i[a], since addition is commutative). Thanks to pointer arithmetic and array-to-pointer decay, you can use this syntax for both arrays and pointers-to-array-elements:

int a[10];
int * b = a + 4;
int * c = malloc(sizeof(int) * 100);

a[2];   // third element of a
b[1];   // sixth element of a
c[3];   // fourth element of the array starting at c

free(c);  // don't forget to clean up!

As to your first problem: There is indeed only limited space available for automatic variables. Overrunning this space is called... stack overflow.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
2

What you also can try is to put the big array as a static variable - out of the stack area. Probably you won't have segfault any more.

lang2
  • 11,433
  • 18
  • 83
  • 133