2010-01-31 5 views
17

Ссылка перераспределить говорит:Как обновить другие указатели, когда realloc перемещает блок памяти?

Функция может перемещать блок памяти на новое место, и в этом случае новое место возвращается.

Означает ли это, что если я это сделать:

void foo() { 

     void* ptr = malloc(1024); 

     unsigned char* cptr = (unsigned char*)ptr+256; 

     ptr = realloc(ptr, 4096); 
} 

тогда CPTR может стать недействительным, если перераспределить перемещает блок?

Если да, то каким-либо образом передается сигнал realloc, чтобы он перемещал блок, чтобы я мог что-то сделать, чтобы cptr не стал недействительным?

+0

Это хороший вопрос +1 от меня, поскольку он подчеркивает фундаментальную кривую обучения, включающую realloc ... – t0mm13b

ответ

6

Да, cptr станет недействительным, так как realloc перемещает блок! И нет, нет упоминания о том, что вы сигнализируете о том, что он перемещает блок памяти. Кстати, ваш код выглядит iffy ... читайте дальше ... см. Мой answer на другой вопрос и очень внимательно прочитайте код о том, как он использует realloc. Общее мнение таково, если вы сделаете это:

 
void *ptr = malloc(1024); 

/* later on in the code */ 

ptr = realloc(ptr, 4096); 

/* BAM! if realloc failed, your precious memory is stuffed! */ 

способ обойти это использовать временный указатель и использовать его, как показано:

 
void *ptr = malloc(1024); 

/* later on in the code */ 

void *tmp = realloc(ptr, 4096); 

if (tmp != null) ptr = tmp; 

Edit: Благодаря Secure за то, что указал гремлин, который закрался, когда я печатал это раньше.

+0

Это не настоящий код - это просто что-то, чтобы показать, что я собираюсь делать. Итак, есть ли способ изменить размер существующего блока памяти, не перемещая его (или сообщить программе, что это невозможно?). Если я вызову realloc, и это удастся, переместив блок, то возможно ли каким-то образом сохранить старые адреса, чтобы я мог «отменить» realloc? – zajcev

+0

Нет! Вы не можете этого сделать ... это зависит от компилятора/компоновщика/времени выполнения. И нет, вы не можете сохранить старые адреса, так как куча будет фрагментирована по курсу и продолжительности жизни программы. Короче говоря, вы не можете полностью привязать старые адреса, поскольку сама суть указателей основана на динамической адресации ... и нет, вы не можете отменить realloc ... – t0mm13b

+0

Это самый бесполезный перевод возвращаемого значения malloc I ' когда-либо видел. И почему вы возвращаете malloc, но не возвращаете realloc? – Secure

3

Да.

Лучше всего сравнить ptr до и после перераспределения и посмотреть, было ли оно перемещено. Вы не должны назначать указатель на значение смещения, вместо этого вы должны сохранить смещение, а затем проиндексировать его исходным оператором.

т.е.

Вместо void* newPtr = ptr + 10; *newPtr = something;

Использование int new = 10; ptr[new] = something;

2

Да, CPTR становится недействительным, если перераспределить перемещает блок.

+0

сожалеет о крике, но это помогло получить короткий ответ за минимальное требование длины. – bmargulies

4

Да, cptr станет недействительным, если realloc перемещает блок.

Нет, сигнала нет. Вам нужно будет проверить возвращаемое значение в исходном местоположении ptr.

4

Это происходит немного поздно, но решение этой проблемы (о которой никто не упомянул) заключается не в использовании указателей на выделенные блоки, которые необходимо будет выделить. Вместо этого используйте целочисленные значения смещения от базового указателя или (лучше) используйте элементы типа struct и элементы-члены для адресации определенных мест в выделенном объекте.

+0

Жаль, что у меня это было до того, как я написал свое текущее задание. Я также думаю, что это часть ответа на ОПЗ Зайцева, объясняя, что он может с этим поделать. – gone

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