I am working on a UDP socket program in windows visual studio.
I am getting an error for sprintf statement. How to correct it?
My code is:
for (i = 0; i < 30;i++) //take-off
{
printf("send AT*REF:take off\n");
sprintf(command, "AT*REF=%d,290718208\r", seq++);
rc = sendto(sd, command, strlen(command) + 1, flags, (struct sockaddr *) &droneAddr, sizeof(droneAddr));
if (rc<0) {
printf("%s: can not send data\n", argv[0]);
return(1);
}
}
The errors I am getting are :
Error 1 error C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
Error 1 error LNK2019: unresolved external symbol __imp__bind@12
Error 2 error LNK2019: unresolved external symbol __imp__htonl@4 referenced in function _main
Error 3 error LNK2019: unresolved external symbol __imp__htons@4
Error 4 error LNK2019: unresolved external symbol __imp__sendto@24
Error 5 error LNK2019: unresolved external symbol __imp__socket@12
Error 6 error LNK2019: unresolved external symbol __imp__gethostbyname@4
Error 7 error LNK1120: 6 unresolved externals
[error C4996: ‘sprintf’: This function or variable may be unsafe. 】Solution
@[TOC]
turn
Visual Studio 2013 compilation error [error C4996: ‘sprintf’: This function or variable may be unsafe.] solution
March 20, 2017 20:48:13
Green squat
Reading number: 6052
Collapse
<div class="tags-box space">
<span class="label">Personal Classification:</span>
<a class="tag-link" href="https://blog.csdn.net/ture_dream/article/category/6412766" target="_blank">C++ Programming </a>
</div>
</div>
<div class="operating">
</div>
</div>
</div>
</div> (write the custom directory title here)
Compile the C++ language project in VS 2013. If you use the sprintf function, you will get the following error when compiling:
Error 5 error C4996: ‘sprintf’: This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. F:\C++\HECHEN\HECHEN\FE.cpp 13 1 HECHEN
The reason is that Visual C++ 2013 uses more secure run-time library routines. New Security CRT functions (those with the «_s» suffix), see:
《Security-enhanced version of the CRT function》
The solution to this problem is given below:
Method 1: Replace the old old function with the new Security CRT functions.
Method 2: Mask this warning with the following method:
1. In the precompiled header file stdafx.h (note: be sure to include any header files before) define the following macro:
#define _CRT_SECURE_NO_DEPRECATE
2. or declare#param warning(disable:4996)
3. Change the preprocessing definition:
Project -> Properties -> Configuration Properties -> C / C + + -> Preprocessor -> Preprocessor definition, add:
_CRT_SECURE_NO_DEPRECATE
Reference material:Security template overload》
Intelligent Recommendation
More Recommendation
- Remove From My Forums
-
Question
-
Now I know that print formatting is available through stream operators, but how can this be used when printing to strings- i cant find anything in std::string (or am I missing something) and I presume there is no inherent method of using string << int etc. Any ideas?
Thanks
Answers
-
Current compiler (and RTM one) not only prints that the function is deprecated, it also prints «safe» function that can be used instead.
It suggests using sprintf_s() instead of sprintf().
Example:
#include <stdio.h>
#include <stdlib.h>char* test (char *buffer, size_t length, int n)
{
sprintf (buffer, «%d», n);
return buffer;
}Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50712 for 80×86
Copyright (C) Microsoft Corporation. All rights reserved.z.cpp
z.cpp(6) : warning C4996: ‘sprintf’ was declared deprecated
C:\Program Files\Microsoft Visual Studio 8\VC\INCLUDE\stdio.h(345) : see declaration of ‘sprintf’
Message: ‘This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.’Thanks,
Eugene -
Have you tried using sprintf_s instead?
Thanks,
Ayman Shoukry
VC++
Я пытаюсь избавиться от некоторых предупреждений компилятора, которые говорят, что strcpy, sprintf и т.д. небезопасны.
Я понимаю, почему они небезопасны, но я не могу придумать хороший способ исправить код в стиле С++.
Здесь выдержка из кода:
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. Подробнее см. Интерактивную справку.
Я не могу думать о безопасном способе копирования данных на С++, не зная длины копируемого материала.
Я знаю, что strlen(), но это также небезопасно, поскольку он предполагает (может быть, неправильно), что данные заканчиваются нулями.
также:
// used to concatenate:
sprintf(extStr,"%s%s",platExtStr,glExtStr);
C4996: ‘sprintf’: эта функция или переменная может быть небезопасной. Рассматривать используя sprintf_s. Чтобы отключить устаревание, используйте _CRT_SECURE_NO_WARNINGS. Подробнее см. Интерактивную справку.
Использование std::string для конкатенации достаточно просто, но тогда мне нужно каким-то образом получить данные в extStr (и не использовать strcpy, lol). Функция string:: c_str() возвращает указатель на un-modifiable data, поэтому я не могу просто установить extStr равным ему. (И я даже не уверен, должен ли указатель c_str() нуждаться в удалении, вызванном на нем позже? Распределяет ли пространство с помощью «new»?)
Какие-нибудь советы по этому поводу?
Это часть файла с 10 000 строк, который не принадлежит мне… поэтому я не очень люблю переписывать вещь на С++.
Ответ 1
Вам действительно не нужны прагмы, чтобы отключить их.
Для win32/msvc в ProjectProperties → Свойства конфигурации → C/С++ → Препроцессор → Определения препроцессора, добавьте следующие макросы:
_CRT_SECURE_NO_DEPRECATE
_CRT_NONSTDC_NO_DEPRECATE
Или вы можете передать thos в параметрах командной строки (-D_CRT_SECURE_NO_DEPRECATE). Вероятно, вы можете #define их в начале определенных файлов *.cpp.
Кроме того, их, вероятно, больше (см. Crtdefs.h — похоже, их много…). Эти предупреждения обычно сообщают вам, с какими макросами вы можете их отключить — просто прочитайте вывод компилятора.
Ответ 2
Если избавиться от предупреждений, это ваша цель… просто определите это _CRT_SECURE_NO_WARNINGS
и он будет подавлять все предупреждения об устаревании. Но это не устранит основные проблемы с небезопасными функциями CRT.
Если вы на Visual Studio версии >= 2005 и хотите исправить эти предупреждения правильно… Самый простой способ — #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
и #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 1
в вашем проекте.
без каких-либо дополнительных изменений кода вы можете заметить, что большинство предупреждений фиксируются автоматически. При определении этого окна автоматически вызовет защищенные перегруженные функции для большинства небезопасных функций CRT. Буферные размеры для статических массивов рассчитываются автоматически.
Хотя динамически распределенные буферы не фиксируются таким образом, и мы должны исправить их вручную. Подробнее см. эту ссылку.
Ниже приведен способ исправления вашего примера программно
strcpy_s(extList->names[i], length, extName);
Ответ 3
Вот еще один ответ на этот вопрос.
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4996)
#endif
strcpy(destination, source);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
Ответ 4
Вы знаете, сколько копировать — вы выделили для этого место!
Неужели вы не захотите копировать больше, чем место, которое вы выделили?
Я бы предпочел использовать метод, который явно избегает переполнения буфера, ограничивая количество копируемых элементов. Когда я был программистом на 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). При копировании строк вам необходимо обеспечить следующее:
- Защитите себя от неправильного ввода, например, неиспользуемую или чрезмерно длинную строку.
- Защитите себя от сбоев malloc,
- Сильно предпочитайте копировать подсчитанные числа символов для копирования, пока мы не увидим нулевое значение
- Если вы заявляете, что хотите построить строку, то решительно убедитесь, что null завершает ее.
Если strlcpy() доступен в вашей среде, вы можете использовать его, иначе почему бы не написать свою собственную небольшую полезность? Тогда, если в этой функции есть предупреждения, вы локализировали проблему.
Ответ 5
В первом примере вы уже знаете длину. Поскольку вы не выделяете length+1
байты, я предполагаю, что length
ВКЛЮЧАЕТ нулевой ограничитель. В этом случае просто std::copy
строка: std::copy(extName, extName + length, expList->names[i]);
В вашем втором примере, предполагая, что исходные строки имеют нулевое завершение, вы можете вычислить длину строки назначения и снова использовать std::copy
для конкатенации вручную или вы можете использовать std::string
и std::copy
из результатов c_str
в пункт назначения (опять же, полагая, что вам выделено достаточно места для него).
c_str()
не выделяет память, для которой требуется внешнее удаление.
Наконец, обратите внимание, что sizeof(char)
всегда будет одним и, следовательно, избыточным в вашем malloc, хотя число бит в этом символе может не быть 8 (см. CHAR_BIT
).
Ответ 6
Я думаю, что вы должны заменить все функциональные вызовы , если возможно,, чтобы вызвать собственную реализацию. Хорошим примером здесь была бы функция замены strcpy и вызов в ней конкретной версии strcpy, основанной на компиляторе. Затем ваша реализация может быть легко модифицирована в соответствии с любым вашим компилятором, особенно если вы будете добавлять или изменять платформы/компиляторы.
Пример:
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
}
Ответ 7
Если переносимость не вызывает беспокойства, вы можете использовать ‘strcpy_s’.
Ответ 8
Если этот код нужно компилировать только для платформы Windows, лучше использовать защищенную версию этих функций. Однако, если этот код собирается скомпилировать на нескольких платформах (linux, Aix и т.д.), Либо вы можете отключить предупреждение в файле конфигурации проекта Windows (например,.vcxproj) с помощью _CRT_SECURE_NO_WARNINGS или вы можете использовать фрагмент кода, например это в тех местах, где эти функции были вызваны в .cpp файле.
#if _OS_ == _OS__WINDOWS
//secure function call
#else
//already written code
#endif
Первоначально предназначенный для чтения 10 изображений за раз, код выглядит следующим образом:
for (int i = 0; i < 10; i++)
{
char filePath[20];
sprintf(filePath, "./imgs/%d.jpg", i);
cout << "filePath: " << filePath << endl;
}
Ошибка при использовании строки формата sprintf, подсказка:
error C4996: ‘sprintf’: This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
Сообщите, что функция sprintf может быть небезопасной, вместо этого рекомендуется использовать sprintf_s, поэтому первое решение — напрямую заменить имя функции, и другие параметры не нужно изменять (в VS2015)
for (int i = 0; i < 10; i++)
{
char filePath[20];
sprintf_s(filePath, "./imgs/%d.jpg", i);
cout << "filePath: " << filePath << endl;
}
Второй способ, согласно подсказкам, добавить _CRT_SECURE_NO_WARNINGS в проект — свойства — свойства конфигурации — C / C ++ — препроцессор — определение препроцессора