0

I am having problems when using a function to allocate arrays in another function. Here is the segment that causes problems:

void
array_allocator(int method, int** a, int** b){
  if (method == 0)
  {
    (*a) = (int[5]) {0, 1, 2, 3, 4};
    (*b) = (int[5]) {5, 6, 7, 8, 9};

    printf ("in array_allocator\n");
    printf ("a = (%d, %d, %d, %d, %d)\n",(*a)[0],(*a)[1],(*a)[2],(*a)[3],(*a)[4]);
    printf ("b = (%d, %d, %d, %d, %d)\n",(*b)[0],(*b)[1],(*b)[2],(*b)[3],(*b)[4]);
  }
  else printf("unknown method\n");
}

void
some_function (int method){
  int *a, *b;

  array_allocator(method, &a, &b);

  printf ("in some_function\n");
  printf ("a = (%d, %d, %d, %d, %d)\n",a[0],a[1],a[2],a[3],a[4]);
  printf ("b = (%d, %d, %d, %d, %d)\n",b[0],b[1],b[2],b[3],b[4]);
}

int main()
{
  int method = 0;
  some_function(method);
  return 0;
}

After compiling with gcc and executing I get the output:

in array_allocator
a = (0, 1, 2, 3, 4)
b = (5, 6, 7, 8, 9)
in some_function
a = (10, 0, 4196346, 0, 1448083200)
b = (-730692608, 32637, 16, 0, 4196346)

Somehow, the values after the array allocation become random, and even change if I add some printf() function before printing the array values at some_function().

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • 2
    You aren't actually allocating. You probably want `malloc`. A more advanced possibility is to divide up an existing block (perhaps even static/global memory) and call it "allocated", but you can't use stack memory like you are doing. I recommend `malloc` or an OS call to get memory. – VoidStar Aug 06 '15 at 19:01

4 Answers4

2

In your array_allocator() function, you're using compound literal.

Regarding the usage of the compound literal, quoting the C11 standard, chapter §6.5.2.5, (emphasis mine)

[...] If the compound literal occurs outside the body of a function, the object has static storage duration; otherwise, it has automatic storage duration associated with the enclosing block.

So, once your function returns, the compound literal does not exist anymore. Thereby, dereferencing a in some_function() is in turn UB.

Solution: You may want to use dynamic memory allocation through malloc() or family. Lifetime of dynamically allocated memory remain valid unless deallocated by using free() call (or, to be nit-picky, until program termination, whichever is earlier), so even after the function returns, you can make use of the same.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
0

The problem here is scope: your array_allocator only allocates the arrays for the duration of its own execution. The 'allocated' arrays are local to the scope of array_allocator so when it returns they may no longer be used.

To allocate memory that outlives the caller's scope, use malloc. But don't forget to also free it!

Kninnug
  • 7,992
  • 1
  • 30
  • 42
0

a and b are local variables of array_allocator. Local variables are on the stack and only available when inside the function. After you return the stack gets overwritten, including your a and b. What you see are those new 'random' stack values.

You need to use malloc. But then you must make sure that you're freeing the memory after you're done with a and b.

Read up on pointers and arrays in C; there's plenty of good material online just a duckduckgo search away.

meaning-matters
  • 21,929
  • 10
  • 82
  • 142
  • the problem is not that they are local; it's that they have automatic storage duration. if the objects were `static`, the code would work, despite the variables being local. Furthermore, there's no need to mention "the stack" – as far as C is concerned, there is no "stack". It's an admittedly common implementation detail, however it's irrelevant since the abstract semantics of the language in itself is enough to describe why the code in question is incorrect. – The Paramagnetic Croissant Aug 06 '15 at 19:13
  • @TheParamagneticCroissant Yes the problem is that they are local. But you're right that they also should not be `static`. I'm trying to give a pragmatic (pun intended) explanation to what seem to be a beginner issue. That's why I also mentioned the stack and did not give a theoretical explanation that makes things only less clear. – meaning-matters Aug 06 '15 at 19:20
0

This doesn't work, as the values you assign only exist locally:

(*a) = (int[5]) {0, 1, 2, 3, 4};
(*b) = (int[5]) {5, 6, 7, 8, 9};

You should instead do this:

*a = malloc(sizeof(int)*5);
*b = malloc(sizeof(int)*5);
(*a)[0] = 0;
(*a)[1] = 2;
(*a)[2] = 2;
(*a)[3] = 3;
(*a)[4] = 4;
(*b)[0] = 5;
(*b)[1] = 6;
(*b)[2] = 7;
(*b)[3] = 8;
(*b)[4] = 9;

Also, don't forget to free(a) and free(b) at the end of some_function()

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Thanks for your reply, I thought that doing (*a) = (int[5]){0,1,2,3,4} was the same that allocating memory and later defining the inputs, but apparently is not. Thanks. – David Ciro Aug 06 '15 at 19:45