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

Как fopen_s быть более безопасным, чем fopen?

Я работаю над устаревшим кодом для платформы Windows. Когда я компилирую код в VS2013, он дает следующее предупреждение:

"ошибка C4996: 'fopen': эта функция или переменная может быть небезопасной. Вместо этого используйте fopen_s. Для отключения устаревания используйте _CRT_SECURE_NO_WARNINGS. Подробнее см. интерактивную справку."

И это также даст овальное предупреждение для sprintf. Я понимаю, что sprintf_s более безопасен, чем sprintf из-за переполнения буфера.

Но как можно fopen_s быть более безопасным, чем fopen, нет возможности переполнения буфера, потому что fopen не принимает буфер. Может ли кто-либо предоставить случай fopen небезопасно, а fopen_s безопасен?

4b9b3361

Ответ 1

В этом случае s не означает "безопасный", это означает "повышенная безопасность". Для fopen_s параметры проверяются на достоверность перед попыткой открыть файл.

С помощью fopen вы можете передать указатель NULL для имени файла, и все, скорее всего, распадется. fopen_s не имеет такой задачи (a).

Имейте в виду, что эти интерфейсы проверки границ, такие как fopen_s, являются необязательной частью стандарта ISO, подробно описанной в Приложении K (как и на C11, в любом случае). Реализации не обязаны предоставлять их, и, если честно, fopen и многие другие так называемые небезопасные функции, совершенно безопасны, если вы знаете, что делаете в качестве кодера.

Интересно отметить, что fopen_s будет улавливать NULL-указатели для вас, но не недействительные указатели, поэтому почему безопасность повышена, а не безопасна - вы все равно можете нанести какой-то ущерб, если вы передадите недопустимый, но не NULL-указатель.

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


(a) Из C11 K.3.5.2.1 The fopen_s function:

errno_t fopen_s (
    FILE * restrict * restrict streamptr,
    const char * restrict      filename,
    const char * restrict      mode);

<сильные > Runtime-ограничения

Ни один из streamptr, filename или mode не должен быть нулевым указателем.

Если есть нарушение ограничения времени выполнения, fopen_s не пытается открыть файл. Кроме того, если streamptr не является нулевым указателем, fopen_s устанавливает * streamptr в нулевой указатель.

Контрастируйте это с помощью C11 7.20.5.3 The fopen function, в котором указано, что имя файла и режим должны указывать на строку, но не указывать, что произойдет, если вы указали указатель NULL (большинство реализаций, скорее всего, сбой с разыменованием нулевого указателя).