0

I have trouble reducing the size of dynamically created array. Here's what my main function looks like:

int main(void) {
    // Intialize big array
    int * a = (int *)malloc(10*sizeof(int));
    assert(a);
    // Fill it with squares
    for (int i = 0; i < 10; ++i)
        a[i] = i*i;
    // Expected to print 64
    printf("%d\n", a[8]);
    // Shrink the big array
    int * b = (int *)realloc(a, 5*sizeof(int));
    assert(b);
    // Expected to cause SEGFAULT
    printf("%d\n", b[8]);
    return 0;
}

Everything works fine except for printf("%d\n", b[8]); line, as it prints 64, but not causing SEGFAULT error as I expected it to. Why?

I think I missing something simple, because I've seen lots of SO questions related to shrinking the memory with realloc, but all of them say that it's possible.

I'm using Ubuntu 14.04 with GCC 4.8.2 and compiling it with -std=c99 option.

vaultah
  • 44,105
  • 12
  • 114
  • 143
  • 1
    This question, or an almost identical one, was asked within the last couple of days — but I can't immediately find it. Although `realloc()` returns the memory to its internal pool of available memory, and any attempt to read or write from it leads to undefined behaviour, it does not unmap the memory usually, so accessing it usually doesn't directly cause a crash — but it is very bad practice to read from freed memory, and far worse to write to freed memory. – Jonathan Leffler May 14 '14 at 06:33
  • _{Rewrite]_ Not sure about the suggested duplicate. The proposed duplicate has nothing to do with `realloc()` or `malloc()`. At the moment, I don't have a good duplicate to point to, but I've not done a thorough search. I suspect that the 'close to duplicate' I thought I remembered has been deleted by its OP. On the whole, leave this open. – Jonathan Leffler May 14 '14 at 17:34
  • 1
    Yes, both this question and proposed duplicate are about reading and writing data outside the bounds of arrays -- in this case dynamically allocated, in the other, normal (a global variable). To that extent, they are duplicates. But I think there's a difference in emphasis with negative indexes vs accessing what had been legitimate up until the allocated space was shrunk. I won't contest a duplicate closure, but I'd prefer to find a duplicate that addresses dynamically allocated memory and shrinkage more explicitly. – Jonathan Leffler May 14 '14 at 17:35

4 Answers4

8

b[8] in the second printf call accesses memory which is not allocated and invokes undefined behaviour. That's what basically undefined behaviour means. The result is unpredictable. It might seem to be working fine but the next time it may, very well, crash. There are few other things to consider here -

  • malloc can fail to allocate memory so checking its return value with the assert macro is wrong. assert should be used to debug impossible or wrong code like accessing an array out of its bound.

  • You should not cast the result of malloc. Do I cast the result of malloc?

  • realloc may fail to reallocate a memory block like malloc. When it fails, it returns NULL and leaves the older block unchanged. This means you would lose handle on the older memory block causing it to leak. You should store the pointer to the older block in a variable before calling realloc.

Community
  • 1
  • 1
ajay
  • 9,402
  • 8
  • 44
  • 71
5

You are accessing unallocated space. That is undefined behaviour. In the worst case, like now, it still works. Segfault is not guaranteed to happen.

user694733
  • 15,208
  • 2
  • 42
  • 68
1

Realloc will just mark the remaining buffer available for future malloc operations. It is UB, if no malloc happened on that buffer you are able to still access that buffer, that is what happened in your case. You are just lucky on not getting segfault on accessing unallocated memory.

Balu
  • 2,247
  • 1
  • 18
  • 23
1

it is undefined, when you do following it could crash or not, depending if the memory you are accessing belongs to your process or not:

int i;
int a[5];
for(i=0;i<10;i++)
  printf("%d\n", a[i]);

you have to check it yourself.

linluk
  • 1,650
  • 16
  • 33