Я пытаюсь избавиться от некоторых предупреждений компилятора, которые говорят, что strcpy, sprintf, и т.д. небезопасны. Я добираюсь, почему они небезопасны, но я не могу думать о хорошем способе исправить код в стиле C++.
Вот выборка кода:
extList->names[i]=(char *)malloc(length*sizeof(char));
strcpy(extList->names[i],extName); // unsafe
// strncpy(extList->names[i],extName,length); // also unsafe
Вот сообщение:
C4996: 'strcpy': Эта функция или переменная могут быть небезопасными. Рассмотрите использование strcpy_s вместо этого. Для отключения депрекации используйте _CRT_SECURE_NO_WARNINGS. Посмотрите справку онлайн для деталей.
Я не могу думать о безопасном способе скопировать данные в C++, не зная, что длина материала копирует. Я знаю, что существует strlen (), но это также небезопасно, так как он принимает (возможно, неправильно), что данные завершаются пустым указателем.
Также:
// used to concatenate:
sprintf(extStr,"%s%s",platExtStr,glExtStr);
C4996: 'sprintf': Эта функция или переменная могут быть небезопасными. Рассмотрите использование sprintf_s вместо этого. Для отключения депрекации используйте _CRT_SECURE_NO_WARNINGS. Посмотрите справку онлайн для деталей.
Используя станд.:: строка для конкатенации достаточно легка, но затем я должен получить данные в extStr так или иначе (и не использующий strcpy, lol). Строка:: c_str () функция возвращает указатель на немодифицируемые данные, таким образом, я не могу просто установить extStr, равный ему. (И я даже не уверен, должен ли c_str () указатель удалить, обратился к нему позже? Это выделяет место, использующее "новый"?)
Совет относительно этого материала? Это - часть 10 000 файлов строки, это не является моим..., таким образом, я не точно увлечен перезаписью вещи в C++ путь.
На самом деле вам не нужны прагмы, чтобы отключить их.
Для win32/msvc, в ProjectProperties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions, добавьте следующие макросы:
_CRT_SECURE_NO_DEPRECATE
_CRT_NONSTDC_NO_DEPRECATE
Или вы можете передать их в параметрах командной строки (-D_CRT_SECURE_NO_DEPRECATE). Возможно, вы можете #define их в начале определенных *.cpp файлов. Кроме того, их, вероятно, больше (см. crtdefs.h - похоже, их много...). Подобные предупреждения обычно сообщают, с помощью каких макросов их можно отключить - просто прочитайте вывод компилятора.
В первом примере вы уже знаете длину. Поскольку вы не выделяете length + 1
байт, я предполагаю, что length
ВКЛЮЧАЕТ нулевой ограничитель. В этом случае просто std :: copy
строка: std :: copy (extName, extName + length, expList-> names [i]);
Во втором примере предполагается, что исходные строки заканчиваются нулем, вы можете вычислить длину целевой строки и снова использовать std :: copy
для объединения вручную, или вы можете использовать std :: string
и std: : скопируйте
из результатов c_str
в пункт назначения (опять же при условии, что вы выделили для него достаточно места).
c_str ()
не выделяет память, которая требует внешнего удаления.
Наконец, обратите внимание, что sizeof (char)
всегда будет равным единице, поэтому он является избыточным в вашем malloc, хотя количество битов в этом символе может не равняться 8 (см. CHAR_BIT
) .
Я думаю, что вам следует заменить все вызовы функций если это возможно на вызов собственной реализации. Хорошим примером здесь может быть функция, заменяющая strcpy и вызывающая внутри себя специфическую для компилятора версию strcpy. После этого ваша реализация может быть легко модифицирована под любой компилятор по вашему выбору, особенно если вы будете добавлять или менять платформы/компиляторы.
Example:
char* StringCopy(char* Destination, const char* Source, size_t DestinationSize)
{
#ifdef _MSC_VER
return strcpy_s(Destination, Source, DestinationSize);
#else
if(!(strlen(Source) >= DestinationSize))
return strcpy(Destination, Source);
else
return 0x0;
#endif
}
Вы знаете, сколько копировать - вы выделили для этого место!
Неужели вы не захотите скопировать больше места, чем выделено вами?
Я бы предпочел использовать метод, который явно избегает переполнения буфера, ограничивая количество копируемых элементов. Когда я был программистом на C, мы использовали
dest = malloc(len); // note: where did we get len?
if ( dest is null ) panic! // note: malloc can fail
strncpy(dest, src, len);
dest[len-1] =0;
. Это немного беспорядочно, и, как уже отмечалось, используется метод strncpy (), который изначально был разработан для полей фиксированной ширины, а не для строк. Однако это действительно так.
Существуют такие методы, как strdup () и strlcpy (), которые могут нам помочь.
Мои рекомендации:
1). Ваша цель не должна заключаться в подавлении предупреждений, а в том, чтобы сделать код надежным.
2). При копировании строк вам необходимо обеспечить следующее:
Если strlcpy () доступен в вашей среде, тогда вы могли бы его использовать, иначе почему бы не написать свою собственную небольшую полезную функцию? Тогда, если есть предупреждения только в той функции, которую вы локализовали, тогда проблема.
Если переносимость не волнует, можно использовать 'strcpy_s'.