Answered by:
snprintf

-
I'm trying to build a project that uses snprintf in Visual C++ 2008 Express Edition. I have #define snprintf _snprintf and #include <stdio.h>, but I get the following warning and error:
warning C4013: 'snprintf' undefined; assuming extern returning int
error LNK2001: unresolved external symbol _snprintf
In the stdio.h I cannot see the _snprintf declaration. Is _snprintf missing in VC++ 2008?
Question
Answers
-
>warning C4013: 'snprintf' undefined; assuming extern returning int
>error LNK2001: unresolved external symbol _snprintf
The messages you have shown will only occur if two
conditions exist:
(1) You are compiling as C and not as C++
(2) You have actually reversed the arguments in the
define statement like this:
#define _snprintf snprintf
Example which generates that warning and error:
#ifdef __cplusplus
#error Build as C only to see problem!
#endif
#include <stdio.h>
#define _snprintf snprintf
int main(void)
{
char buffer[100];
_snprintf(buffer, sizeof(buffer), "Ciao.");
printf("%s\n", buffer);
return 0;
}
- Wayne- Marked as answer by Nancy Shao Friday, January 29, 2010 9:05 AM
All replies
-
I believe _snprintf is available in Express Edition as well (you won't find ATL and MFC in Express, but the CRT is there).This works fine in VS2008, I would suggest you try it in Express Edition as well (I don't have Express to test it).c:\TEMP>type test.cpp#include <stdio.h>int main(void){char buffer[100];_snprintf(buffer, sizeof(buffer), "Ciao.");printf("%s\n", buffer);return 0;}c:\TEMP>cl /EHsc /nologo /W4 /MT /O2 /GL test.cpptest.cpptest.cpp(6) : warning C4996: '_snprintf': This function or variable may be unsafe. Consider using _snprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\INCLUDE\stdio.h(358) : see declaration of '_snprintf'Generating codeFinished generating codec:\TEMP>test.exeCiao.
-
-
>warning C4013: 'snprintf' undefined; assuming extern returning int
>error LNK2001: unresolved external symbol _snprintf
The messages you have shown will only occur if two
conditions exist:
(1) You are compiling as C and not as C++
(2) You have actually reversed the arguments in the
define statement like this:
#define _snprintf snprintf
Example which generates that warning and error:
#ifdef __cplusplus
#error Build as C only to see problem!
#endif
#include <stdio.h>
#define _snprintf snprintf
int main(void)
{
char buffer[100];
_snprintf(buffer, sizeof(buffer), "Ciao.");
printf("%s\n", buffer);
return 0;
}
- Wayne- Marked as answer by Nancy Shao Friday, January 29, 2010 9:05 AM
-
-
I know Microsoft can afford to be different and send to hell all the standards, but why?!? why not just declare snprintf in the headers? they are not getting more revenue by doing that.
Free advertising? All the code has
#ifdef WIN32
#define snprintf _snprintf
#endif
-
Thanks the "#define snprintf _snprintf" worked after the compiler v8 suggested to use snprintf_s but compiler then generated an error if /wx flag was turned on otherwise a warning something the person who developed _snprintf/snprintf_s function should have recommended to use this "#define" in the msdn library where the snprintf_s function is explained. It shouldn't take a third party to figure it out, how much time got wasted in trial and error?
-
I don't know why this was marked as an answer, because it's simply not true. At least not in Visual Studio 2013. Maybe it was true for an earlier version.
The code I'm working on:
* is compiled as C,
* does not define _snprintf,
* uses snprintf - not _snprintf,
* includes stdio.h
and it shows the warning as well.
-
The code I'm working on:
* is compiled as C,
* does not define _snprintf,
* uses snprintf - not _snprintf,
* includes stdio.h
and it shows the warning as well.
To which warning are you referring? If you mean the one about it being unsafe, that isn't
what the OP was seeing. The original issue was that the compiler was saying it couldn't
find snprintf and the linker was saying that _snprintf was undefined - an error not a
warning.
- Wayne
-
I don't know why this was marked as an answer, because it's simply not true. At least not in Visual Studio 2013. Maybe it was true for an earlier version.
Did you not notice that this thread was started and marked as answered six years ago?
All references at the time are clearly stated as using VS/VC++ 2008.
If you have a problem it's usually better to start a new thread of your own rather than
tack your issue onto the end of a very old thread - especially one that has been marked
as answered since many people will skip over such threads if they're looking for problems
that need to be resolved for others.
- Wayne
-
> I don't know why this was marked as an answer, because it's simply not true. At least not in Visual Studio 2013. Maybe it was true for an earlier version.
Addition of the "real" snprintf is one of "breaking changes" since VS 2015 (or even 2013 with some update).
- Edited by Pavel A Sunday, February 14, 2016 12:58 AM
-
I come late to the party but...
_snprintf was written before snprintf was defined in C99 and Microsoft's C compilers prior to Visual Studio 2015 have been largely stuck at C89.
DO NOT replace snprintf with _snprintf with #define for any reason.
Use _snprintf_s instead if you lack C99's snprintf. You should avoid using _snprintf in any context where you don't control the number of formatted bytes that will be placed in the buffer.
_snprintf will fail to terminate a string with a '\0' character if the length of the formatted data string is greater or equal to the count argument to the function.
In C99 snprintf will safely terminate C strings if the formatted string exceeds the size of the buffer but Microsoft's _snprintf will not terminate the string.
Writing this will leave the string array unterminated:
#include <stdio.h>
int main() { char arry[10]; _snprintf(arry, sizeof arry, "Something much greater than 10 characters."); printf("%s\n", arry); return 0; }
If you don't have snprintf then writing this will be safe:
#include <stdio.h> int main() { char arry[10]; _snprintf_s(arry, sizeof arry, sizeof arry-1, "Something much greater than 10 characters."); printf("%s\n", arry); return 0; }
This is why Microsoft's compilers issue the C4996 warning for functions like _snprintf.
Here is unified sample of code you can run in VS2015 that tests all three functions:
#include <stdio.h> int main() { char array[10]; int len; char *string = "Something much greater than 10 characters."; len = snprintf(array, sizeof array, "%s", string); if (len > sizeof array) puts("Error! Possible unterminated string."); printf("snprintf returned %d and array contains: ", len); printf("%s\n\n", array); len = _snprintf_s(array, sizeof array, sizeof array-1, "%s", string); if (len > sizeof array) puts("Error! Possible unterminated string."); printf("_snprintf_s returned %d and array contains: ", len); printf("%s\n\n", array); len = _snprintf(array, sizeof array, "%s", string); if (len > sizeof array) puts("Error! Actual unterminated string!"); printf("_snprintf returned %d and array contains: ", len); printf("%s\n\n", array); return 0; }
Output from a sample debugging run:
Error! Possible unterminated string.
snprintf returned 42 and array contains: SomethingError! Possible unterminated string.
_snprintf_s returned -1 and array contains: SomethingError! Actual unterminated string!
_snprintf returned -1 and array contains: Something ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠(₧÷⌂- Proposed as answer by chong kyong kim Wednesday, October 5, 2016 1:33 AM
- Edited by QwazyWabbit Wednesday, October 5, 2016 4:11 AM Not a buffer overflow but an unterminated string state.
-
As documented, all these functions do not overwrite or overflow the buffer. That's they will not write past sizeof array. But _snprintf in the example will not write the null terminator. The garbage will be printed because of reading past end of the buffer (that is bad as well).
To ensure the null terminator with _snprintf, write it in the last char of the buffer:
len = snprintf(array, count, "%s", string); array[count-1] =0;
and be happy.
Of course, the real c99 snprintf is preferred for compatibility with other compilers, but it is not available before VS2015.
VS 2015 breaks quite a lot of legacy code which defined their own snprintf (correctly or not), it will error out because of duplicate definition. To fix, surround the definition of snprintf with #if _MSC_VER < 1900 .
- Edited by Pavel A Wednesday, October 5, 2016 2:36 AM
-
try
#include <stdio.h>
#define snprintf _snprintf_sint main(void)
{
char buffer[10];
snprintf(buffer, sizeof(buffer), sizeof buffer -1,"123456789012345");
printf("%s\n", buffer);//prints '123456789'char array[15];
snprintf(array, sizeof(array), sizeof array -1,"1234567890123456");//prints '123456789012345'
printf("%s\n", buffer);
return 0;
} -