1

We were shown this program in class yesterday and i have a question regarding it's output.

malloc.c:

#include <stdlib.h>

int *create_array(int);

int *create_array(int elements) {
    int i,*x = (int *) malloc(elements*sizeof(int));

    for(i=0;i < elements;i++) {
        x[i] = i;
    }
    free(x);
    return x;
} 

int main(void) {
    int j, *arr;
    arr = create_array(5);
    for(j=0;j<5;j++) {
        printf("%d\n",arr[j]);
    }
    return 0;
}

Question(s):

When i run the program, i get this as output:

1627793032
1627793104
2
3
4

However, shouldn't the first 2 elements be 0 and 1 respectively? The values printed here seem like memory addresses to me, am i right? Also, is this due to some mistake causing undefined behavior?

Stelios Papamichail
  • 955
  • 2
  • 19
  • 57
  • 1
    When you call free `free(x)`, the pointer to `x` becomes a `dangling pointer` which is basically a pointer to memory you don't own anymore. It is completely possible the program crashes with `segfault` if another program has been granted access to that freed memory region. – Strong will Nov 17 '18 at 22:53
  • thank you both for the info, now everything makes sense. – Stelios Papamichail Nov 17 '18 at 23:07

2 Answers2

5

After free(x);, the values pointed to by x are no longer valid. The memory can be reused for some other purpose, and meanwhile the memory allocation library can use the storage as it sees fit.

So, yes, it is a mistake resulting in undefined behaviour.

rici
  • 234,347
  • 28
  • 237
  • 341
3

The real question is why do you even expect it to work? You free x, then you return a freed pointer which is nonsense.

What is happening is the following:

  • Inside the function you allocate 5 spaces, x points to the first one's address.

  • You write 0, 1, 2, 3, 4 in these spaces.

  • You free x, so all the 5 spaces are not reserved anymore.

  • You exit the function, doing so the 2 next free memory spaces are used, which happen to be the ones where you wrote 0 and 1.

  • You print the values contained in the 5 memory areas you've already freed, where the ones in which you wrote 0 and 1 happen to have been reused for something else; hence the weird numbers.

As a general rule, do not attempt to read areas of memory i've freed; even worse, do not try to WRITE there.

Accessing unallocated memory leads to undefined behaviour.

Also, you don't need to declare the function in a separate row if it's going to have nothing in between; plus you don't have to cast what's returned by malloc to the type; it's a void* that by default can hold anything you throw at it. What matters is your base variable type. See here

Corrected code:

#include <stdlib.h>

int *create_array(int elements) {
    int i,*x = malloc(elements*sizeof(int));

    for(i=0;i < elements;i++) {
        x[i] = i;
    }
    return x;
} 

int main(void) {
    int j, *arr;
    arr = create_array(5);
    for(j=0;j<5;j++) {
        printf("%d\n",arr[j]);
    }
    free(arr);
    return 0;
}
klutt
  • 30,332
  • 17
  • 55
  • 95
Barnack
  • 921
  • 1
  • 8
  • 20