I have faced a compiler error(c3861) in my newly installed Visual studio community 2015 IDE:
I just want to use gets() function from stdio.h library, and i have included stdio.h file in my program, but compiler show me a compiler error
like below:
error C3861: 'gets': identifier not found
What should i do to compile my program correctly withgets() function.
Since C11, gets is replaced by gets_s. The gets() function does not perform bounds checking, therefore this function is extremely vulnerable to buffer-overflows. The recommended replacements are gets_s() or fgets()
gets_s(buf);
fgets(buf, sizeof(buf), stdin);
if you are looking forward to learn about
buffer overflow vulnerability
you simply can use it and anther unsafe functions by the fallowing steps
from the solution explorer right click on the project and choose properties
navigate to Configuration Properties >> C/C++ >> Advanced
change Compile As value to Compile as C Code (/TC)
(optional) if you would like to disable the warning just put its warning number in disable specific warning
The gets function was considered too dangerous (because it can easily cause a buffer overflow), so it was removed from the latest revisions of both C and C++.
You are supposed to use fgets instead. With that function you can limit input to the size of your buffer.
gets and_getws are removed from the beginning of vs 2015 because these functions are obsolete.
Alternative functions are gets_s and _getws_s.
Related
This question already has an answer here:
Why didn't gcc (or glibc) implement _s functions?
(1 answer)
Closed 3 years ago.
When I use visual studio, it says "scanf is unsafe, try using scanf_s". But if I use scanf_s in gcc or other compilers, it doesn't work. Does scanf_s works only on visual studio? If so, why? The visual studio website says "scanf is unsafe". If it is unsafe, then why others still uses it?
As mentioned here
scanf_s is Microsoft-specific. Header is stdio.h but not in GCC.
As documented here
When reading a string with scanf, always specify a width for the %s format (for example, "%32s" instead of "%s"); otherwise, improperly formatted input can easily cause a buffer overrun.
Alternately, consider using scanf_s, _scanf_s_l, wscanf_s, _wscanf_s_l or fgets.
See more at "Why didn't gcc implement _s functions?"
pmg adds in the comments that scanf_s() is Standard C11 (optional).
That means that activating c11 with gcc might be enough.
However Shawn adds:
IIRC, Microsoft's version doesn't follow the standard.
Plus no other major C library vendor has bothered to implement Annex K, so it might as well be MS specific for all intents and purposes.
pmg confirms:
My gcc (version 6.3.0) does not recognize scanf_s() with gcc -std=c11 -pedantic ...
I am using Visual Studio 2015 and ReSharper for my C programs but I can not make gets method work in this IDE. Why is this method not shown in autocomplete list?
From the C documentation:.
The gets() function does not perform bounds checking, therefore this function is extremely vulnerable to buffer-overflow attacks. It cannot be used safely (unless the program runs in an environment which restricts what can appear on stdin). For this reason, the function has been deprecated in the third corrigendum to the C99 standard and removed altogether in the C11 standard. fgets() and gets_s() are the recommended replacements.
Never use gets().
I'm developing a program without using CRT , so, some third party using very naive implementation of memset() likes:
char x[10];
for(int i= 0; i< 10; i++) {
x[i] = '\0';
}
It's alot of this type of code in that 3rd party library, and, I do not like messing around with it, so, how could I prevent Visual Studio from automatically converting from for loop to memset() ?
Edit: Why this is a problem ?
Since, my program does not use CRT, so, if Visual Studio auto converts the for loop to memset(), it will cause the error:
Unresolved external symbol _memset
The only relevant compiler option I see in the list of compiler options, besides disabling optimization, is /kernel, which produces a binary that can run in the Windows kernel. That is a big hammer; it alters compilation in several ways. Building for the kernel is something one might expect would instruct the compiler not to use library routines. However, the specific page for that switch does not mention it, so I doubt the switch includes that.
Given this, I do not think Visual Studio has a feature of producing stand-alone code that does not use library routines.
If I correctly remember, MSVC used to have an option for explicitely not use the C run time library. My version was not English, but it should be something like: Use standard libraries. It was used to produce an executable with no dependancies beyond Windows API, which is your current requirement.
According to the MSVC page about NODEFAULTLIB, the option still exists on recent versions and should do what you need:
If you use /NODEFAULTLIB, for example, to build your program without the C run-time library, you may have to also use /ENTRY to specify the entry point (function) in your program.
I could not test (no access to a MSVC installation), but I would bet a coin that MSVC will not try to use a function from the CRT when you set this option.
IMHO, MSVC should not optimize the loop to a memset call, because it defeats a stand alone environment build. Anyway, a possible workaround is to provide à private memset version wrapping the WinAPI function ZeroMemory.
My book says the get_s() function is a better alternative to the gets() function, which is deprecated and should not be used. But, when I try to use the get_s() function it always gives me an error:
undefined reference to gets_s
This page says something about the gets_s, function that I didn't really understand about it being defined in the ISO/IEC 99. Shouldn' t it work with all the compilers? I'm pretty sure I'm using a very recent version of the MinGW compiler.
How should I use this function? Is using the gets() or scanf() (instead of scanf_s()), or fgets() over fgets_s(), not good?
yes you are right #bumblebee
The gets() function does not perform bounds checking, therefore this function is extremely vulnerable to buffer-overflow attacks. It cannot be used safely (unless the program runs in an environment which restricts what can appear on stdin). For this reason, the function has been deprecated in the third corrigendum to the C99 standard and removed altogether in the C11 standard. fgets() and gets_s() are the recommended replacements.
Never use gets().
source: http://en.cppreference.com/w/c/io/gets
check weather you included the corresponding header. and one more thing u have to see is that weather you c comiler version is an updated version or the old version that can also create a problem.. so try in a c11 standard ,or a c11 online compiler
During early 90s or so, gets() was found to be flawed by design since it would keep reading data forever until it found the end of a string, which meant it could cause buffer overflows either accidentally or through security exploits.
Therefore gets was flagged as an obsolescent function in the C99 standard. Meaning that from the year 1999, people were warned that it should not be used.
The function was removed entirely from the language in the C11 standard, meaning that there was a very generous transit period of no less than 12 years to fix legacy code. It was replaced by gets_s, as a safe alternative to be used when porting old code to C11. It takes the buffer size as second parameter.
However, gets_s should only be used for such C11 porting reasons, if at all. gets_s is part of the optional bounds-checking interface in C11 and compilers need not implement it. The C11 standard recommends to use fgets instead:
Recommended practice
The fgets function allows properly-written
programs to safely process input lines too long to store in the result
array. In general this requires that callers of fgets pay attention to
the presence or absence of a new-line character in the result array.
Consider using fgets (along with any needed processing based on
new-line characters) instead of gets_s.
Note that gets_s has little to do with the non-standard Visual Studio compiler, even though that compiler happens to support this function, just as the standard conforming compilers that support the bounds-checking interface (__STDC_LIB_EXT1__) do.
When I am using Visual Studio (MSVC), and using the strcat function, I get the error
error C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
If I was to make a project which was for compilers like GCC aswell, is there a way of detecting if these safe functions are needed, for example MSVC macro?
You can use conditional compilation for cross-platform code. Such as:
#ifdef WIN
strcat_s(...
#else
strcat(...
#endif
MSVC compiler detects such calls of the functions that were acknowledged as deprecated and generates warning C4996 on level 3. So, just compile with this level (or more) and look at warnings.
Usually I use #ifdef _CRT_INSECURE_DEPRECATE for this. It's the macro used by Visual to add these warnings in the first place, so if you're compiling on a version of Visual that gives warnings, it will be defined.