2014-01-26 2 views
1

У меня есть следующий код:Realloc просто ничего не diong, не erroring

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

int main(int argc, char ** argv) 
{ 
    //just checking to see where the stack 
    printf("The stack is around %p\n", &argc); is, making sure arr isn't in it 
    char ** arr = malloc(8*sizeof(char*)); 
    printf("arr is size %li, at %p\n", sizeof(arr), arr); 
    arr = realloc(arr, 100); //I picked a weird number to show it isn't doing anything. I've picked different numbers (like 200, 2*sizeof(char*)*sizeof(arr), and 16) 
    printf("arr is size %li, at %p\n", sizeof(arr), arr); 
} 

Это совокупность файла (это тестовый блок, я замечал это в другом месте)

Выход из вышеизложенного:

The stack is around 0x7fff5b94d12c 
arr is size 8, at 0x120f010 
arr is size 8, at 0x120f010 

Возможно, я не понимаю, что должен сделать realloc. Я ожидающий следующий выход.

The stack is around 0x7fff5b94d12c 
arr is size 8, at 0x120f010 
arr is size <size>, at <somewhere> 

где <size> это ... что-то странное, как 12 ... по крайней мере 8 и <somewhere> скорее всего 0x120f010, но, возможно, где-нибудь разумное.

Являются ли мои ожидания неправильными или неправильно использую realloc?

+3

Настоящая проблема в том, что вы недопонимаете 'sizeof' ... –

+0

Вы правы, я. Спасибо ... теперь отлаживать оригинальную программу. –

ответ

1

Вывод вашей программы является правильным, потому что

  • Ни malloc, ни realloc имеют ничего общего с автоматическим хранением (т.е. «в стек»). Они выделяют память из динамической области хранения (т. Е. «Куча»). Не следует ожидать, что позиция верхней части стека изменится в ответ на вызовы malloc, realloc, или, если на то пошло, любую другую функцию.
  • Значение sizeof(arr) не зависит от того, что вы ему выделили. Он вычисляется во время компиляции и всегда равен размеру указателя. В вашей системе указатели используют 8 байтов.
  • malloc часто дает вам больше памяти, которую вы запрашиваете, и сохраняет фактическое значение в специальном месте, к которому realloc может получить доступ позднее. Если вы realloc вниз или realloc в пределах, значение, возвращаемое realloc, не изменяется. Вот почему он может работать лучше, чем просто звонить malloc и memcpy.
+0

Спасибо за ваш ответ (который я, очевидно, нашел наиболее точным, хотя Эд тоже был замечателен). Что касается стека против кучи, я просто пытался удостовериться, что не ошибаюсь и не переписываю части с помощью стека. В исходной программе у меня возникали проблемы, похожие на то, что некоторые строки были перезаписаны (они были: я перераспределял пространство, намного меньшее, чем необходимо), поэтому именно эта строка там. –

1
sizeof arr 

Это так же, как

sizeof char** 

Размер указателя не изменится, и принимая размер указателя не будет сказать вам, сколько памяти она ссылается. Указатели не являются массивами, а sizeof оценивается во время компиляции.

Что касается бита адреса, realloc не гарантирует, что блок памяти был перемещен. Он мог бы просто успешно расширить его и вернуть тот же адрес.

Кроме того, я понимаю, что это всего лишь пример кода, но имейте в виду, что если realloc не удалось, вы просочились в то, что первоначально указывал arr.

+2

Педантичность: в C99 'sizeof' может быть операцией времени выполнения (если используется в массиве переменной длины). См. Http://stackoverflow.com/q/10078283/575615 – Medo42

+0

@ Medo42: Ах, да, хороший звонок. Я писал C на земле C89 некоторое время, не думал об этом. –

0

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

Это не то, от чего вы должны когда-либо зависеть. Это просто причуда реализации

+0

На самом деле это не совсем то, на что стоит обратить внимание. –

0

Если ваше предположение состоит в том, что realloc() должен возвращать другой указатель, то ваше предположение неверно.

Как правило, если Вы уменьшаете размер выделенной памяти или оставить «как есть», то realloc() может возвращать один и тот же указатель и избежать копирования данных и т.д.

Иногда, если вы увеличить размер выделенной памяти realloc() может проверить, есть ли свободное пространство над существующим пространством и по-прежнему возвращать тот же указатель (и не копировать данные).

В основном, только когда свободного пространства над выделенной памятью нет, realloc() должен скопировать данные в другое место и вернуть другой указатель.

Смежные вопросы