Поделиться через


Безопасные перегрузки шаблонов

Корпорация Майкрософт объявила устаревшими многие функции библиотеки C времени выполнения (CRT), заменив их версиями с более высоким уровнем безопасности. Например, strcpy_s является более безопасной заменой для strcpy. Устаревшие функции являются общими источниками ошибок безопасности, так как они не препятствуют операциям, которые могут перезаписать память. По умолчанию компилятор выдает предупреждение об устаревании, если в коде присутствует любая из этих функций. CRT предоставляет для этих функций перегруженные шаблоны C++, которые помогают упростить переход к более безопасным вариантам.

Например, для этого фрагмента кода создается предупреждение, поскольку функция strcpy объявлена устаревшей:

char szBuf[10];
strcpy(szBuf, "test"); // warning: deprecated

Предупреждение об устаревании сообщает вам, что используемый код может быть небезопасным. Если вы проверили, что код не может перезаписать память, у вас есть несколько вариантов. Вы можете просто игнорировать это предупреждение. Вы можете добавить символ _CRT_SECURE_NO_WARNINGS перед инструкциями include в заголовках CRT, чтобы подавить предупреждение. Также вы можете изменить код, заменив эту функцию на strcpy_s:

char szBuf[10];
strcpy_s(szBuf, 10, "test"); // security-enhanced _s function

Перегрузки шаблона предоставляют больше возможностей. Если определить _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES значение 1, он включает перегрузки шаблонов стандартных функций CRT, которые вызывают более безопасные варианты автоматически. Если _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES имеет значение "1", никаких изменений в коде не требуется. Вызов функции strcpy в фоновом режиме заменяется вызовом функции strcpy_s с автоматической подстановкой аргумента размера.

#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1

// ...

char szBuf[10];
strcpy(szBuf, "test"); // ==> strcpy_s(szBuf, 10, "test")

Макрос _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES не влияет на функции, которые принимают число, например strncpy. Чтобы включить перегруженные шаблоны для функций, принимающих количество, определите _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT как значение "1". Однако перед этим действием следует убедиться, что код передает количество символов, а не размер буфера (частая ошибка). Кроме того, код, который явно записывает значение NULL в конец буфера после вызова функции, является необязательным, если вызывается безопасный вариант. Если требуется поведение усечения, см. раздел _TRUNCATE.

Примечание.

Макрос _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT требует, чтобы _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES также был определен как значение "1". Если _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT определен как значение "1" и _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES определен как значение "0", в приложении не выполняются никакие перегрузки шаблонов.

Если вы определите _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES со значением "1", включается перегрузка шаблонов безопасными вариантами (имена которых оканчиваются на "_s"). В этом случае, если _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES определен как значение "1", в исходном коде необходимо сделать одно небольшое изменение.

#define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1

// ...

char szBuf[10];
strcpy_s(szBuf, "test"); // ==> strcpy_s(szBuf, 10, "test")

Требуется изменить только имена функций (добавив к ним символы "_s"), а перегрузка шаблона автоматически подставит аргумент размера.

По умолчанию _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES и _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT определены как "0" (запрещено), а _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES определен как "1" (разрешено).

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

#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1

// ...

char *szBuf = (char*)malloc(10);
strcpy(szBuf, "test"); // still deprecated; change it to
                       // strcpy_s(szBuf, 10, "test");

И в этом примере:

#define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1

// ...

char *szBuf = (char*)malloc(10);
strcpy_s(szBuf, "test"); // doesn't compile; change it to
                         // strcpy_s(szBuf, 10, "test");

См. также

Функции безопасности в CRT
Файлы среды выполнения C (CRT) и стандартной библиотеки C++ (STL) .lib