Почему 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 при доступе к нераспределенной памяти.