none
snprintf

    Question

  • 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?


    Friday, January 22, 2010 11:28 AM

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
    Saturday, January 23, 2010 5:49 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.cpp
    test.cpp
    test.cpp(6) : warning C4996: '_snprintf': This function or variable may be unsaf
    e. Consider using _snprintf_s instead. To disable deprecation, use _CRT_SECURE_N
    O_WARNINGS. See online help for details.
            C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\INCLUDE\stdio.h(35
    8) : see declaration of '_snprintf'
    Generating code
    Finished generating code

    c:\TEMP>test.exe
    Ciao.

    Friday, January 22, 2010 11:54 AM
  • And works fine in Visual C++ 2008 Express =)
    Friday, January 22, 2010 11:57 AM
  • >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
    Saturday, January 23, 2010 5:49 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.
    Thursday, September 1, 2011 12:52 PM
  • 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

    Thursday, November 10, 2011 7:55 PM
  • 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?  
    Thursday, December 29, 2011 9:09 PM
  • 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.

    Friday, February 12, 2016 11:16 AM
  • 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

    Friday, February 12, 2016 7:26 PM
  • 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

    Friday, February 12, 2016 7:35 PM
  • > 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).

    See here for details.


    • Edited by Pavel A Sunday, February 14, 2016 12:58 AM
    Friday, February 12, 2016 11:16 PM
  • 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: Something

    Error! Possible unterminated string.
    _snprintf_s returned -1 and array contains: Something

    Error! 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.
    Tuesday, October 4, 2016 10:06 PM
  • 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
    Tuesday, October 4, 2016 11:48 PM
  • try

    #include <stdio.h>
    #define snprintf _snprintf_s
    int 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;
    }

    Wednesday, October 5, 2016 2:13 AM
  • Quite correct. I had buffer overflow on the brain because I was dealing with one when I landed on this topic. My post has been amended. Good call.
    Wednesday, October 5, 2016 4:12 AM