0

I am trying to dynamically create an array in a separate function and store some variables inside of that array and I came across the following: how come when I write;

#include <stdio.h>
#include <stdlib.h>

void foo(int **arr, int N) {
  *arr = malloc(sizeof(int));

  for (int index = 0; index <= 4; index++) {
    *arr[index] = 1;
  }
}

int main() {
  int *arr; 
  foo(&arr, 5);

  for (int bar = 0; bar <= 4; bar++) {
    printf("%d ", arr[bar]);
  }
}

I get this output;

exited, segmentation fault

However, when I run the following;

#include <stdio.h>
#include <stdlib.h>

void foo(int **arr, int N) {
  *arr = malloc(sizeof(int));
}

int main() {
  int *arr; 
  foo(&arr, 5);

  for (int index = 0; index <= 4; index++) {
    arr[index] = 1;
  }

  for (int bar = 0; bar <= 4; bar++) {
    printf("%d ", arr[bar]);
  }
}

I get this output;

1 1 1 1 1

I am stuck trying to figure out how to fix the first block of code to get it to work, but I seem to have no idea how to do so. Any help would be appreciated in at least understand why a segmentation fault occurs.

Cizox
  • 165
  • 1
  • 9

2 Answers2

1

There are a couple of things going on here that are important details.

Evgeny is correct that you need to allocate N things of sizeof int. Otherwise your program is wrong, and will write to invalid memory locations.

The cause of the segment violation took a few minutes to track down. I added printf statements throughout your code so as to be able to see where the segment violation occurred. It showed that the assignment of 1 to the array element was where it was happening.

I then suspected that the binding/order was the issue, so put the parenthesis around the *arr to make it very clear that it was the intent. The segment violation went away after that. I also changed the initialization to index so the assignment results would be easily verifiable.

#include <stdio.h>
#include <stdlib.h>

void foo(int **arr, int N) 
{
    *arr =(int *) malloc(sizeof(int) * N);

    for (int index = 0; index < N; index++)
    {
        printf("before assignment\n");
        (*arr)[index] = index;
        printf("after assignment\n");
    }
}

int main() 
{
  int *arr; 
  foo(&arr, 5);

  for (int bar = 0; bar < 5; bar++) 
  {
    printf("%d ", arr[bar]);
  }
}

In short, a useful quick and dirty technique is to insert a bunch of printfs to help narrow down where the issue is happening.

EvilTeach
  • 28,120
  • 21
  • 85
  • 141
  • Well that was easier than I thought. Is it because of the way the order of precedence works with pointers '*arr[index]' is treated as '*(arr[index])'? – Cizox Oct 19 '19 at 21:14
  • Take a look at this. https://stackoverflow.com/questions/51373516/array-syntax-vs-pointer-syntax-and-code-generation/51373661 it talks about array syntax vs pointer syntax. – EvilTeach Oct 19 '19 at 21:26
0

malloc requires full memory size, including array size. So the correct code would be

*arr = malloc(sizeof(int) * N);
Evgeny Bovykin
  • 2,572
  • 2
  • 14
  • 27