Почему realloc не уменьшает массив?

У меня проблемы с уменьшением размера динамически создаваемого массива. Вот что мой main функция выглядит так:

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;
}

Все отлично работает кроме printf("%d\n", b[8]); линия, как она печатает 64, но не вызывает ошибку SEGFAULT, как я ожидал. Зачем?

Я думаю, что упустил что-то простое, потому что я видел много ТАКИХ вопросов, связанных с сокращением памяти с reallocНо все они говорят, что это возможно.

Я использую Ubuntu 14.04 с GCC 4.8.2 и собираю его с -std=c99 вариант.

4 ответа

Решение

b[8] во-вторых printf вызов обращается к памяти, которая не выделена и вызывает неопределенное поведение. Вот что в основном означает неопределенное поведение. Результат непредсказуем. Может показаться, что он работает нормально, но в следующий раз может произойти сбой. Есть несколько других вещей, чтобы рассмотреть здесь -

  • malloc может быть не в состоянии выделить память, поэтому проверка его возвращаемого значения с помощью assert макрос не так. assert должен использоваться для отладки невозможного или неправильного кода, например, доступа к массиву за его пределами.

  • Вы не должны разыгрывать результат malloc, Я использую результат malloc?

  • realloc может не перераспределить блок памяти как malloc, Когда это терпит неудачу, это возвращает NULL и оставляет старый блок без изменений. Это означает, что вы потеряете управление старым блоком памяти, что приведет к его утечке. Вы должны сохранить указатель на старый блок в переменной перед вызовом realloc,

Вы получаете доступ к незанятому пространству. Это неопределенное поведение. В худшем случае, как сейчас, все еще работает. Segfault не гарантируется.

Он не определен, если вы выполните следующее, это может привести к сбою или нет, в зависимости от того, принадлежит ли память, к которой вы обращаетесь, вашему процессу или нет:

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

Вы должны проверить это сами.

Realloc просто пометит оставшийся буфер, доступный для будущих операций malloc. Это UB, если в этом буфере не произошло malloc, вы можете получить доступ к этому буферу, что и произошло в вашем случае. Вам просто повезло, что вы не получили segfault при доступе к нераспределенной памяти.

Другие вопросы по тегам