Подтвердить что ты не робот

Безопасно ли использовать realloc?

Некоторое время назад мой друг сказал мне не использовать realloc, потому что это небезопасно, но он не мог сказать мне, почему, поэтому я провел некоторое исследование по этому вопросу, и ближайшие ссылки на мои сомнения были:
https://buildsecurityin.us-cert.gov/bsi/articles/knowledge/coding/809-BSI.html
http://www.iso-9899.info/wiki/Why_not_realloc
Я хочу знать, могу ли я продолжать использовать realloc в моем коде, или если это небезопасно, есть ли другой способ перераспределения памяти? Спасибо за внимание.

4b9b3361

Ответ 1

Первая из двух связанных статей поднимает две жалобы выше и выше "проверенных вызовов успешно", которые уже подняты здесь.

Когда это будет сделано, старое содержимое будет отброшено и где-нибудь останется в памяти. Для приложений с защищенной памятью, где важно стереть все следы данных, это поведение неуместно.

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

Поскольку он перемещает память вокруг, любые старые указатели на эту память становятся недействительными и могут привести к сбою программы или, как следствие, к неправильной работе.

Этот момент кажется мне бессмыслицей. Их предлагаемое решение не лучше, они malloc(), копируют, а затем free() оригинал, который имеет тот же чистый эффект - адрес изменился. Если вы хотите избежать перемещения памяти, вы можете использовать некоторые вызовы конкретной платформы, чтобы сделать это, если вы устроили для них достаточное свободное адресное пространство рядом с ними. Если бы вы знали априори, сколько адресного пространства зарезервировано, то вы, вероятно, не подумали бы называть realloc(), в первую очередь, хотя!

Если вы играете в азартные игры на realloc(), никогда не двигаясь, всегда растут, тогда у вас, вероятно, возникли большие проблемы, чтобы беспокоиться о любом случае, и переход на malloc() + copy + free() не может решить этого.


Помимо "проверить правильное значение возвращаемого значения", наиболее интересным моментом из второй статьи является предупреждение о:

Не переустанавливайте буфер на 1 байт за раз.

они предупреждают:

Это гарантированно приведет к сбою памяти.

Это потенциально допустимая точка, но это не критика самого realloc(); то же самое произойдет, если вы использовали malloc() + copy + free(). Реальное решение заключается в том, чтобы вырастить буферы разумно, независимо от того, как вы их вырасти или лучше, но распределите в правильных размерах куски спереди.

Они также имеют точку в

Использование realloc для возврата памяти в систему.

Они верны здесь, поскольку использование любого размера, отличного от 0, может фактически не сделать возврат. Это, вероятно, делает вещи не хуже, но это использование по-прежнему кажется примером преждевременной "оптимизации". Исправление снова состоит в том, чтобы начать использовать разумные размеры.

Сортировка ответа: это небезопасно, но это не волшебное решение для всех ваших проблем.

Ответ 2

Совершенно безопасно использовать 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;

Ответ 3

realloc безопасен сам по себе, но его безопасное использование немного сложнее - до такой степени, что я бы сказал, что примерно 85-90% кода, который я видел, который использует его, не делает это безопасно. Проблема заключается в том, что realloc возвращает NULL для указания отказа, но когда он это делает, указатель, который вы указали как вход, по-прежнему действителен (при условии, что вы не изменили его распределение до 0).

Следовательно, вы должны назначить возврат из realloc указателю, который вы указали как ввод, если и только если realloc возвратил ненулевой указатель. Если он возвращает нулевой указатель, ваш предыдущий указатель действителен, но распределение не изменяется.

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

Ответ 4

Как и все на C, до тех пор, пока вы знаете, что вы делаете, это прекрасно.

(Знание того, что вы делаете, включает проверку ошибок, не используйте старый указатель и т.д.)