Pergunta

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.

Foi útil?

Solução

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.

Outras dicas

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

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.

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top