Безопасно ли использовать realloc?
некоторое время назад мой друг сказал мне не использовать realloc, потому что это небезопасно, но он не мог сказать мне, почему, поэтому я сделал некоторые исследования по этому вопросу и ближайшие ссылки на мои сомнения were:
https://buildsecurityin.us-cert.gov/bsi/articles/knowledge/coding/809-BSI.html
http://www.iso-9899.info/wiki/Why_not_realloc
Я хочу знать, могу ли я продолжать использовать realloc в своем коде или если это небезопасно, есть ли другой способ перераспределения память?
Спасибо за внимание.
4 ответов
первая из двух связанных статей поднимает две жалобы выше и за пределами "проверить вызов успешно" пунктов, уже поднятых здесь.
когда это сделано, старое содержимое отбрасывается и остается где-то в памяти. Для защищенных приложений памяти, где важно стереть все следы данных, такое поведение неуместно.
это действительный пункт если вы храните конфиденциальные данные (например, закрытые ключи, нехешированной(!) пароли и т. д.) и хотите сделать его более сложным для эксплойтов для восстановления данных или других процессов в системе, чтобы украсть данные.
поскольку он перемещает память вокруг, любые старые указатели на эту память становятся недействительными и могут привести к сбою программы или иным образом плохо себя вести.
этот пункт кажется мне бессмыслицей. Их предлагаемое решение не лучше, они malloc()
скопировать, а потом free()
оригинал, который имеет тот же эффект адрес изменился. Если вы хотите, чтобы избежать перемещения памяти может иметь возможность использовать некоторые конкретные вызовы платформы, чтобы сделать это, если вы устроили там достаточно свободного адресного пространства рядом с ними. Если бы вы знали ... --16-->априори сколько адресное пространство, чтобы зарезервировать, то вы, вероятно, не будет думать о вызове realloc()
в первую очередь, однако!
если вы играете на realloc()
никогда не движется, всегда растет, вы, вероятно, есть более серьезные проблемы беспокойтесь о любом случае и переключении на malloc()
+ копия + free()
это невозможно решить.
помимо "проверить возвращаемое значение правильно точки", наиболее интересным моментом из второй статьи является предупреждение о:
не перераспределяйте буфер по 1 байту за раз.
они предупреждают:
это гарантированно сбить кучу памяти
это потенциально действует точка, но это не критика realloc()
сам; то же самое произойдет, если вы используете malloc()
+копия+free()
. Реальное исправление состоит в том, чтобы разумно выращивать буферы независимо от того, как вы их выращиваете или еще лучше распределяете в правильных кусках.
они также имеют точку зрения о
использование realloc для возврата памяти в систему.
они правы здесь в том, что использование любого размера, кроме 0, может фактически не возвращать. Наверное делает вещи не хуже, но это использование все еще кажется примером преждевременной "оптимизации". Исправление снова заключается в использовании разумных размеров распределения для начала.
Сортировать ответ: это не небезопасно, но это не волшебное решение всех ваших проблем.
это совершенно безопасно использовать realloc
. Это способ перераспределения памяти в программе на языке C.
однако вы всегда должны проверять возвращаемое значение для условия ошибки. Не попадайтесь в эту общую ловушку:
p = realloc(p, new_size); // don't do this!
если это не удается, realloc
возвращает NULL
и вы потеряли доступ к p
. Вместо этого:
new_p = realloc(p, new_size);
if (new_p == NULL)
...handle error
p = new_p;
realloc
безопасен сам по себе, но использовать его безопасно немного сложно-до такой степени, что я бы сказал, что примерно 85-90% кода, который я видел, использует его не сделать это безопасно. Проблема в том, что realloc
возвращает NULL для обозначения сбоя , но когда это происходит, указатель, который вы указали в качестве ввода, по-прежнему действителен (при условии, что вы не изменили его распределение на 0).
таким образом, вы должны назначить возврат из realloc
к указателю вы поставили как входной сигнал если и только если realloc
возвращает ненулевой указатель. Если он возвращает нулевой указатель, предыдущий указатель действителен, но размер распределения не был изменен.
также обратите внимание, что многие люди предполагают realloc
может только сбой и / или переместить выделение, когда вы увеличить выделение. На самом деле он может потерпеть неудачу (хотя это маловероятно) или переместить данные в другое место (гораздо более вероятно), даже если вы сокращение размер выделения.
Как и все в C, пока вы знаете, что делаете, все в порядке.
(знание того, что вы делаете,включает в себя проверку ошибок, не используйте старый указатель и т. д.)