- Remove From My Forums
-
Question
-
// ptrstr.cpp -- using pointers to strings #include <iostream> #include <cstring> // declare strlen(), strcpy() int main() { using namespace std; char animal[20] = "bear"; // animal holds bear const char * bird = "wren"; // bird holds address of string char * ps; // uninitialized cout << animal << " and "; // display bear cout << bird << "n"; // display wren // cout << ps << "n"; //may display garbage, may cause a crash cout << "Enter a kind of animal: "; cin >> animal; // ok if input < 20 chars // cin >> ps; Too horrible a blunder to try; ps doesn't // point to allocated space ps = animal; // set ps to point to string cout << ps << "!n"; // ok, same as using animal cout << "Before using strcpy():n"; cout << animal << " at " << (int *) animal << endl; cout << ps << " at " << (int *) ps << endl; ps = new char[strlen(animal) + 1]; // get new storage strcpy_s(ps, animal); // copy string to new storage cout << "After using strcpy():n"; cout << animal << " at " << (int *) animal << endl; cout << ps << " at " << (int *) ps << endl; delete [] ps; cin.get(); cin.get(); return 0; }
How to fix this : Error 1 error C4996: ‘strcpy’: This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
I tried using strcpy_s but the following appeared:
Error 1 error C2660: ‘strcpy_s’ : function does not take 2 arguments c:usersalexandrosdocumentsvisual studio 2013projectslisting 4_20listing 4_20ptrstr.cpp 27 1 Listing 4_20
2 IntelliSense: no instance of overloaded function «strcpy_s» matches the argument list
argument types are: (char *, char [20]) c:UsersAlexandrosDocumentsVisual Studio 2013ProjectsListing 4_20Listing 4_20ptrstr.cpp 28 5 Listing 4_20Using VS2013 ultimate
-
Edited by
Tuesday, August 11, 2015 12:03 PM
-
Edited by
Answers
-
ps = new char[strlen(animal) + 1]; // get new storage strcpy_s(ps, sizeof(animal), animal); // copy string to new storag
You allocate strlen(animal) of space for the ps variable, and then in the next line of code, lie to the strcpy_s function and state that you allocated sizeof(animal) number of characters.
-
Edited by
Brian Muth
Tuesday, August 11, 2015 7:09 PM -
Marked as answer by
Shu 2017
Monday, August 24, 2015 6:00 AM
-
Edited by
-
Hi ClassicalGuitar,
If you can guarantee that the destination string has enough space to hold the source string including its null-terminator, just use strcpy() and ignore the compiling warning; if the compiling warning is carking, suppress it with
#define _CRT_SECURE_NO_WARNINGS
or
#pragma warning(disable : 4996)You may also use
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
to let the compiler automatically replaces strcpy() with strcpy_s() for you. See at
https://msdn.microsoft.com/en-us/library/ms175759.aspxFrom the MSDN document about strcpy() and strcpy_s(), the main difference between both is that, if the destination space is not enough, while strcpy() proceeds in silence, strcpy_s() calls default Invalid Parameter Handler Routine to consciously crash the
program and make you be awared of it with a report; see at
https://msdn.microsoft.com/en-us/library/ksazx244.aspx.You may overload the Invalid Parameter Handler Routine with your own function that not terminating the execution; in the case, strcpy_s() returns error; you are required to handle the program flow when the error happens.
If the destination and source strings overlap, the behaviors of strcpy() and strcpy_s() are undefined.
-
Marked as answer by
Shu 2017
Monday, August 24, 2015 6:00 AM
-
Marked as answer by
-
Reply both to Igor Tandetnik and kwick:
Read documentation for warning C4996
In C++, the easiest way to do that is to use Secure Template Overloads, which in many cases will eliminate deprecation warnings by replacing calls to deprecated functions
with calls to the new secure versions of those functions. For example, consider this deprecated call to
strcpy:char szBuf[10]; strcpy(szBuf, "test"); // warning: deprecated
Defining _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES as 1 eliminates the warning by changing the
strcpy call to strcpy_s, which prevents buffer overruns. For more information, see
Secure Template Overloads.The template overloads provide additional choices. Defining _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES to 1 enables template overloads of standard CRT functions that call the more secure variants automatically. If
_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES is 1, then no changes to the code are necessary. Behind the scenes, the call to
strcpy will be changed to a call to strcpy_s with the size argument supplied automatically.It is better for me to use a #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
Now code becomes:
// ptrstr.cpp -- using pointers to strings #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 #include <iostream> #include <cstring> // declare strlen(), strcpy() int main() { using namespace std; char animal[20] = "bear"; // animal holds bear const char * bird = "wren"; // bird holds address of string char * ps; // uninitialized cout << animal << " and "; // display bear cout << bird << "n"; // display wren // cout << ps << "n"; //may display garbage, may cause a crash cout << "Enter a kind of animal: "; cin >> animal; // ok if input < 20 chars // cin >> ps; Too horrible a blunder to try; ps doesn't // point to allocated space ps = animal; // set ps to point to string cout << ps << "!n"; // ok, same as using animal cout << "Before using strcpy():n"; cout << animal << " at " << (int *) animal << endl; cout << ps << " at " << (int *) ps << endl; ps = new char[strlen(animal) + 1]; // get new storage strcpy(ps, animal); // copy string to new storage cout << "After using strcpy():n"; cout << animal << " at " << (int *) animal << endl; cout << ps << " at " << (int *) ps << endl; delete [] ps; cin.get(); cin.get(); return 0; }
and compiles and run without errors.
This issue is solved!
-
Marked as answer by
ClassicalGuitar
Friday, August 28, 2015 5:27 PM
-
Marked as answer by
rura 0 / 0 / 0 Регистрация: 08.01.2014 Сообщений: 153 |
||||
1 |
||||
28.04.2014, 20:54. Показов 24270. Ответов 9 Метки нет (Все метки)
Уважаемые форумчане! У меня не работает программа. Все написано «вроде» правильно. Вот сама программа:
__________________
0 |
Модератор 12641 / 10135 / 6102 Регистрация: 18.12.2011 Сообщений: 27,170 |
|
28.04.2014, 21:05 |
2 |
Это не ошибка. VS предлагает для «надежности» использовать другую (левую) функцию.
0 |
0 / 0 / 0 Регистрация: 08.01.2014 Сообщений: 153 |
|
28.04.2014, 21:42 [ТС] |
3 |
Как мне кто-то объяснял, нужно не эту функцию использовать. У меня просто Вижуал 2013. Это говорят из-за него эта программа не запускается. Это так? Добавлено через 29 минут
0 |
KOPOJI Почетный модератор 16842 / 6720 / 880 Регистрация: 12.06.2012 Сообщений: 19,967 |
||||
28.04.2014, 21:55 |
4 |
|||
в тексте ошибки все написано.
2 |
alsav22 5493 / 4888 / 831 Регистрация: 04.06.2011 Сообщений: 13,587 |
||||
29.04.2014, 00:30 |
5 |
|||
Следовательно, либо заменить strcpy на strcpy_s, как советует среда, либо добавить в начале кода
Либо избавиться от таких «ошибок»:
1 |
0 / 0 / 0 Регистрация: 08.01.2014 Сообщений: 153 |
|
29.04.2014, 14:00 [ТС] |
6 |
А что значит «избавиться от ошибки»?
0 |
5493 / 4888 / 831 Регистрация: 04.06.2011 Сообщений: 13,587 |
|
29.04.2014, 14:17 |
7 |
А что значит «избавиться от ошибки»? Чтобы при использовании таких функций, студия перестала выдавать ошибки (что началось с 12-й студии). Это стандартные функции, использование которых никак не является ошибкой (но у microsoft, на этой почве, прогрессирующая паранойя).
0 |
0 / 0 / 0 Регистрация: 08.01.2014 Сообщений: 153 |
|
29.04.2014, 22:33 [ТС] |
8 |
То есть, отключив ошибку, функция будет работать. И не только эта?
0 |
5493 / 4888 / 831 Регистрация: 04.06.2011 Сообщений: 13,587 |
|
29.04.2014, 22:37 |
9 |
Сообщение было отмечено rura как решение РешениеДа.
0 |
0 / 0 / 0 Регистрация: 08.01.2014 Сообщений: 153 |
|
29.04.2014, 22:44 [ТС] |
10 |
Спасибо огромное!
0 |
so I have this code:
#include "stdafx.h"
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
…
char* b = new char [10];
strcpy(b, "1234567890");
error: microsoft visual studio 11.0vcincludestring.h(110) : see declaration of ‘strcpy’
How do I fix it?
asked Aug 30, 2012 at 19:31
Ivan ProdanovIvan Prodanov
34.2k76 gold badges173 silver badges246 bronze badges
5
A quick fix is to add the _CRT_SECURE_NO_WARNINGS definition to your project’s settings
Right-click your C++ and chose the «Properties» item to get to the properties window.
Now follow and expand to, «Configuration Properties»->»C/C++»->»Preprocessor»->»Preprocessor definitions».
In the «Preprocessor definitions» add
_CRT_SECURE_NO_WARNINGS
but it would be a good idea to add
_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
as to inherit predefined definitions
IMHO & for the most part this is a good approach.
answered Oct 24, 2012 at 4:24
There’s an explanation and solution for this on MSDN:
The function strcpy is considered unsafe due to the fact that there is
no bounds checking and can lead to buffer overflow.Consequently, as it suggests in the error description, you can use
strcpy_s instead of strcpy:strcpy_s( char *strDestination, size_t numberOfElements,
const char *strSource );
and:
To disable deprecation, use
_CRT_SECURE_NO_WARNINGS. See online help for details.
http://social.msdn.microsoft.com/Forums/da-DK/vcgeneral/thread/c7489eef-b391-4faa-bf77-b824e9e8f7d2
answered Aug 30, 2012 at 19:42
John HumphreysJohn Humphreys
35.9k34 gold badges149 silver badges249 bronze badges
2
The message you are getting is advice from MS that they recommend that you do not use the standard strcpy function. Their motivation in this is that it is easy to misuse in bad ways (and the compiler generally can’t detect and warn you about such misuse). In your post, you are doing exactly that. You can get rid of the message by telling the compiler to not give you that advice. The serious error in your code would remain, however.
You are creating a buffer with room for 10 chars. You are then stuffing 11 chars into it. (Remember the terminating »?) You have taken a box with exactly enough room for 10 eggs and tried to jam 11 eggs into it. What does that get you? Not doing this is your responsibility and the compiler will generally not detect such things.
You have tagged this C++ and included string. I do not know your motivation for using strcpy, but if you use std::string instead of C style strings, you will get boxes that expand to accommodate what you stuff in them.
answered Aug 30, 2012 at 19:59
Avi BergerAvi Berger
1,9581 gold badge15 silver badges13 bronze badges
I had to use strcpy_s and it worked.
#include "stdafx.h"
#include<iostream>
#include<string>
using namespace std;
struct student
{
char name[30];
int age;
};
int main()
{
struct student s1;
char myname[30] = "John";
strcpy_s (s1.name, strlen(myname) + 1 ,myname );
s1.age = 21;
cout << " Name: " << s1.name << " age: " << s1.age << endl;
return 0;
}
answered Feb 7, 2016 at 21:41
PatPat
3152 silver badges11 bronze badges
4
Add this line top of the header
#pragma warning(disable : 4996)
answered Dec 17, 2019 at 16:57
Rajib ChyRajib Chy
72910 silver badges22 bronze badges
If you are getting an error saying something about deprecated functions, try doing #define _CRT_SECURE_NO_WARNINGS
or #define _CRT_SECURE_NO_DEPRECATE
. These should fix it. You can also use Microsoft’s «secure» functions, if you want.
answered Feb 9, 2017 at 14:20
For my problem, I removed the #include <glui.h>
statement and it ran without a problem.
rayryeng
102k22 gold badges185 silver badges189 bronze badges
answered Nov 2, 2015 at 4:25
1
Содержание
- Error c4996 strcpy this function or variable may be unsafe
- Answered by:
- Question
- Answers
- Error c4996 strcpy this function or variable may be unsafe
- Answered by:
- Question
- Answers
- Error c4996 strcpy this function or variable may be unsafe
- Visual C++: используем _CRT_SECURE_NO_WARNINGS для совместимости с классическими функциями
- Избавляемся от ошибки «This function or variable may be unsafe» в Visual Studio
Error c4996 strcpy this function or variable may be unsafe
This forum has migrated to Microsoft Q&A. Visit Microsoft Q&A to post new questions.
Answered by:
Question
How to fix this : Error 1 error C4996: ‘strcpy’: This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
I tried using strcpy_s but the following appeared:
Error 1 error C2660: ‘strcpy_s’ : function does not take 2 arguments c:usersalexandrosdocumentsvisual studio 2013projectslisting 4_20listing 4_20ptrstr.cpp 27 1 Listing 4_20
2 IntelliSense: no instance of overloaded function «strcpy_s» matches the argument list
argument types are: (char *, char [20]) c:UsersAlexandrosDocumentsVisual Studio 2013ProjectsListing 4_20Listing 4_20ptrstr.cpp 28 5 Listing 4_20
Using VS2013 ultimate
Answers
You allocate strlen(animal) of space for the ps variable, and then in the next line of code, lie to the strcpy_s function and state that you allocated sizeof(animal) number of characters.
If you can guarantee that the destination string has enough space to hold the source string including its null-terminator, just use strcpy() and ignore the compiling warning; if the compiling warning is carking, suppress it with
#define _CRT_SECURE_NO_WARNINGS
or
#pragma warning(disable : 4996)
You may also use
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
to let the compiler automatically replaces strcpy() with strcpy_s() for you. See at https://msdn.microsoft.com/en-us/library/ms175759.aspx
From the MSDN document about strcpy() and strcpy_s(), the main difference between both is that, if the destination space is not enough, while strcpy() proceeds in silence, strcpy_s() calls default Invalid Parameter Handler Routine to consciously crash the program and make you be awared of it with a report; see at https://msdn.microsoft.com/en-us/library/ksazx244.aspx.
You may overload the Invalid Parameter Handler Routine with your own function that not terminating the execution; in the case, strcpy_s() returns error; you are required to handle the program flow when the error happens.
If the destination and source strings overlap, the behaviors of strcpy() and strcpy_s() are undefined.
Источник
Error c4996 strcpy this function or variable may be unsafe
This forum has migrated to Microsoft Q&A. Visit Microsoft Q&A to post new questions.
Answered by:
Question
i’m getting this error while debugging my code:
error C4996: ‘strcpy’: This function or variable may be unsafe.
Those are parts of my code :
There is another warning shown by MS visual c++ runtime library , saying that:
Debug assertion failed!
Expression: (L»Buffer is too small»&&0).
How can i deal with this error? I use VS 2012
Answers
i’m getting this error while debugging my code:
error C4996: ‘strcpy’: This function or variable may be unsafe.
That’s a compilation error. It’s normally a warning, so presumably
you’ve got the /WX option set to treat all warnings as errors.
Read the documentation on the warning:
http://msdn.microsoft.com/en-us/library/ttcz0bys.aspx
If you have to use strcpy, you can supress the warning using
_CRT_SECURE_NO_WARNINGS — again, see the documentation.
There is another warning shown by MS visual c++ runtime library , saying that:
Debug assertion failed!
Expression: (L»Buffer is too small»&&0).
Do yourself a favour — don’t bother writing your own string class, use
the std string class.
Источник
Error c4996 strcpy this function or variable may be unsafe
БлогNot. Visual C++: используем _CRT_SECURE_NO_WARNINGS для совместимости с классическими.
Visual C++: используем _CRT_SECURE_NO_WARNINGS для совместимости с классическими функциями
Часто жалуются на «неработающие» коды, особенно консольных приложений или CLR, особенно тех, что работали без каких-либо замечаний в версиях 2010-2013 и вдруг «не работают» в 2015, например, вот этот код.
Выдаются ошибки типа
Ошибка C4996 ‘strcpy’: This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
Можете, как и рекомендует компилятор, заменить старые названия функций на их безопасные версии, скажем, strcpy на strcpy_s и fopen на fopen_s .
Правда, в последнем случае изменится и «классический» оператор открытия файла, скажем, с
Суть дела в том, что функции, возвращающие указатель, считаются небезопасными, отсюда и изменившийся шаблон метода открытия файла.
Есть путь ещё проще — напишите
в самом начале до всех #include .
Если используется предкомпиляция, то можно определить этот макрос в заголовочном файле stdafx.h .
Можно также попробовать «дорисовать» его не в заголовках, а в настройках проекта.
Управление предкомпилированными заголовками находится вот где: меню Проект — Свойства C/C++ — Препроцессор (Preprocessor) — Определения препроцессора (Preprocessor Definitions).
Проверено на пустом проекте C++ Visual Studio 2015, 2019, сработало.
Некоторым функциям директива «не поможет», например, stricmp всё равно придётся заменять но _stricmp , правда, без изменения списка аргументов.
Заметим, что по стандартам C++ функции strcpy , strcat и другие не устарели, это собственная политика Microsoft.
Источник
Избавляемся от ошибки «This function or variable may be unsafe» в Visual Studio
Время чтения: 5 минут
Компилятор в Visual Studio сильно отличается от привычных большинству программистов GCC или CLANG, из-за чего при написании кода на C или C++ очень часто возникают неожиданные проблемы в виде ошибки использования стандартных функций, например, scanf, fopen, sscanf и тому подобным. Студия предлагает заменять функции на безопасные (повезёт, если нужно просто добавить _s к функции с ошибкой, но нередко в этих функциях идёт иной набор аргументов, нежели в обычной программе). Если вы не готовы с этим мириться, то этот пост для вас!
Давайте для начала создадим обычный консольный проект в Visual Studio и напишем простенькую программу, которая запрашивает ввод двух чисел, вводит их и затем выводит на экран.
Попробовав выполнить сборку проекта, обнаружим те самые ошибки.
Чтобы Visual Studio не тратила ваши нервы, сделаем следующее:
1. Выберем пункт «Проект» в верхнем меню
2. В открывшемся списке щёлкнем по «Свойства название_проекта»
3. В появившемся окне выберем Свойства конфигурации , C/C++ , Препроцессор
4. В строке Определения препроцессора допишем в самый конец строку ;_CRT_SECURE_NO_WARNINGS
6. Попробуем заново выполнить сборку проекта:
Ошибки исчезли, сборка прошла успешно и программа прекрасно работает! Теперь можно писать код как обычно, не переживая о необычном поведении Visual Studio!
Программист, сооснователь programforyou.ru, в постоянном поиске новых задач и алгоритмов
Языки программирования: Python, C, C++, Pascal, C#, Javascript
Выпускник МГУ им. М.В. Ломоносова
Programforyou — это сообщество, в котором Вы можете подтянуть свои знания по программированию, узнать, как эффективно решать те или иные задачи, а также воспользоваться нашими онлайн сервисами.
Источник
Visual C++: используем _CRT_SECURE_NO_WARNINGS для совместимости с классическими функциями
Часто жалуются на «неработающие» коды, особенно консольных приложений или CLR, особенно тех, что работали без каких-либо замечаний в версиях 2010-2013 и вдруг «не работают» в 2015, например, вот этот код.
Выдаются ошибки типа
Ошибка C4996 ‘strcpy’: This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
Можете, как и рекомендует компилятор,
заменить старые названия функций на их безопасные версии, скажем,
strcpy
на strcpy_s
и
fopen
на fopen_s
.
Правда, в последнем случае
изменится и «классический» оператор открытия файла, скажем, с
FILE *out = fopen_s("data.txt", "wt");
на
FILE *out; fopen_s(&out,"data.txt", "wt");
Суть дела в том, что функции, возвращающие указатель, считаются небезопасными, отсюда и изменившийся шаблон метода открытия файла.
Есть путь ещё проще — напишите
#define _CRT_SECURE_NO_WARNINGS
в самом начале до всех #include
.
Если используется предкомпиляция, то можно определить этот макрос в заголовочном файле stdafx.h
.
Можно также попробовать «дорисовать» его не в заголовках, а в настройках проекта.
Управление предкомпилированными заголовками находится вот где: меню Проект — Свойства C/C++ — Препроцессор (Preprocessor) — Определения препроцессора (Preprocessor Definitions).
Проверено на пустом проекте C++ Visual Studio 2015, 2019, сработало.
Некоторым функциям директива «не поможет», например, stricmp
всё равно придётся заменять но _stricmp
, правда, без изменения списка аргументов.
Заметим, что по стандартам C++ функции
strcpy
,strcat
и другие не устарели, это собственная политика Microsoft.
13.10.2015, 11:48 [93995 просмотров]
К этой статье пока нет комментариев, Ваш будет первым
Introduction
Two programmers went to buy cigarettes. One buys them and goes “Dude, did you read this? Warning! Smoking causes lung cancer witch is fatal”. Then the other one says “Yeah, forget the warning, just tell me the errors!”
When using Microsoft Visual Studio 2005 or newer, the compiler may give a bunch of annoying warnings saying something like: “warning C4996: ‘strcpy’: This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details”. CRT functions like strcpy are standard functions, so why the compiler complains? Well, it simply recommends using of more secure versions of CRT functions which have ‘_s’ postfix (strcpy_s instead of strcpy, sprintf_s instead of sprintf and so on). So, at a first look nothing fatal happened and we can go ahead. However, simply ignoring the warnings is not a good practice and moreover someone may work in a company or project in which “zero warnings” is a must.
This article is about how to deal with C4996 warning, what secure CRT functions are and how to correctly use them. Further, let’s call them “_s functions”.
Can we get rid of C4996 warnings?
Especially when porting code written under an older Visual C++ version, we may want to get rid of C4996 warnings. The answer is: yes, we can like in case of other compiler warnings, by adding pragma warning directive in the source code.
#pragma warning(disable: 4996)
You may add pragma warning in each source file or, if the project uses precompiled header, adding only it in StdAfx.h is pretty enough.
Another and better way is to add _CRT_SECURE_NO_WARNINGS to preprocessor definitions, as suggested in the description of the warning. To find out how to add _CRT_SECURE_NO_WARNINGS, take a look in MSDN at /D (Preprocessor Definitions).
No warnings, no more headaches, and the boss is happy. However, please read further! One good way to avoid C4996 warnings is… by using _s functions.
Why using _s functions?
Here, I would like to quote from one of Michael Howard’s articles:
Think about it for a moment. When were functions like strcpy and strcat invented? They were designed in happier times when the C language was first developed by Kernighan and Ritchie long ago, when threats were by no means as serious as they are today, and when networking wasn’t as pervasive as it is today. Now don’t get me wrong, you can write secure code with functions like strcpy. It’s the data that’s the culprit, after all. But functions like strcpy don’t help you write secure code, and an error in such a function can be catastrophic. Of course, gets is just plain evil! ‘Nuff said.
I heard C/C++ programmers saying: “I’ve never ever made a bug”. That’s pretty possible if they never ever made a line of code. Otherwise, I can’t believe them. Nobody is perfect and everyone can do mistakes.
In the first side, standard C functions were designed for speed. For that reason, they do not perform run-time checking which is usually performed in other programming languages. A programmer must be carefully when use those functions and validate parameters in the own code in order to avoid troubles like buffer overrun, access violation, malicious attacks, and so on.
Well, _s functions do additional checking for you. Details about Security Enhancements in the CRT can be found in MSDN library.
I will give just a trivial example concerning null termination string problem. One can say “this is stupid, something like that can never happen”. Wrong! In the real programming world, other ones even more stupid, much more insidious and having uglier effects, can be found.
Two strings walk into a bar. One of them says: “A beer, please!%@8Hj(^&9))%@!$%*” The other one says: “You’ll have to excuse my friend, he is not zero-terminated.”
May be a good programmers’ joke, but in a C/C++ application, a not-zero terminated string is not so funny. Let’s try translating it into code:
#define MAX_BUFFER 1000 void append_joke(char* buff, const char* psz) { strcat(buff, psz); // classic } int main() { char* joke = new char[MAX_BUFFER]; memcpy(joke, "A beer, please!", strlen("A beer, please!")); append_joke(joke, "You'll have to excuse my friend…"); printf(joke); delete []joke; #ifdef _DEBUG system("pause"); #endif return 0; }
If the program doesn’t crash (here because of heap corruption) we can’t say that we are lucky. The result may be a bunch of garbage like in the above joke. But if we use strcat_s instead of strcat, a run-time checking against not properly null terminated string will be performed. Further we’ll see what’s happen in this case.
Do _s functions prevent program crashing?
Most of programmers dealing first time with _s functions think that program will never crash even they are doing mistakes. In other words, simply replacing standard CRT functions with more secure ones, prevents application crashing. That is not true. Let’s modify append_joke function and replace strcat with “more secure” strcat_s.
void append_joke(char* buff, const char* psz) { strcat_s(buff, MAX_BUFFER, psz); // more secure }
Now, let’s run again the program in debug mode. Oups!.. A “Debug Assertion Failed” message box is shown. If press “Ignore” button, another “fatal error” message is shown then program terminates. What happened? First, strcat_s function checks parameters validity. If one is invalid (in our example we have not null terminated string) and if the program runs in debug mode, a “debug assertion failed” message is shown. That’s very good, because we have a chance to fix the mistake, first looking at assertion message (here is “String is not null terminated”), then pressing “Retry” and search the source of error in “Call Stack” window. That is not possible in case of using the “classic” function strcat.
Finally, an invalid parameter handler function is called and the process terminates. That’s also good because, if something is really going bad, it’s preferable to close the application instead of let it doing unpredictable things.
How to customize the _s functions behavior?
As stated above, when _s functions detect an invalid parameter, a message is shown then the application process terminates.
However, someone may want to do something else before application exits or simply wants application to continue. Someone else may wonder why the _s functions return an error code as long as by default, if an invalid parameter is passed, the process is terminated. Well, the default invalid parameter handler function may be replaced with an application-defined one. For doing that, we can call _set_invalid_parameter_handler function.
Here is an example. It prevents showing the debug assertion failure message and sets an application-defined invalid parameter handler function. In case that invalid parameter is passed, the process isn’t terminated. Also, the error code returned by strcat_s is used by program, which prints out the string only if it’s Ok.
#include <string.h> #include <stdio.h> #include <stdlib.h> #include <crtdbg.h> void app_handler(const wchar_t * expression, const wchar_t * function, const wchar_t * file, unsigned int line, uintptr_t pReserved) { wprintf_s(L"%snFunction:%snFile:%snLine:%un", expression, function, file, line); } #define MAX_BUFFER 1000 errno_t finish_joke(char* buff, const char* psz) { return strcat_s(buff, MAX_BUFFER, psz); } int main() { // prevent showing "debug assertion failed" dialog box _CrtSetReportMode(_CRT_ASSERT, 0); // set application-defined invalid parameter handler _set_invalid_parameter_handler(app_handler); char* joke = new char[MAX_BUFFER]; memcpy(joke, "A beer, please!", strlen("A beer, please!")); errno_t ret = finish_joke(joke, "You'll have to excuse my friend…"); if(0 == ret) // prints only if finish_joke succeeded { printf_s(joke); } delete []joke; #ifdef _DEBUG system("pause"); #endif return 0; }
Conclusion
- It’s no sweat to get rid of C4996 warnings but also it’s good to know that secure CRT functions are great.
- Secure CRT functions perform run-time parameters checking which helps to find mistakes and prevent troubles.
- The default invalid parameter handler terminates the aplication process; if we want to change this, we have to use an application-defined handler.
- Last but not the least: if you want to write more solid and secure code, prefer using secure version of CRT functions!
See also
- MSDN: Security Enhancements in the CRT
- Michael Howard: Saying Goodbye to an Old Friend
- Secure CRT Functions Standard