2

I've been looking over this piece of code for a while, and I can't seem to find my bug. I think I know how snprintf(dest, n, fmt, src) is supposed to work ( it returns the number of remaining characters in the src buffer after filling the dest buffer with n characters from the fmt string and the src buffer) but it is not doing what I would expect. Instead of returning the number of remaining characters to be copied, it is returning the total characters copied.

The code below:

 40   char header_file_name[200];
 ....
 87   int n_overflow = 0;
 88   n_overflow = snprintf( header_file_name, 200, "%s.h", template_name );
 89   if ( n_overflow > 0 )
 90   {
 91       printf( "That template name is too large; try a smaller template name\n");
 92       printf("n_overflow = %d\n", n_overflow);
 93       printf("header_file_name = %s\n", header_file_name );
 94       printf("length of header_file_name = %d\n", strlen(header_file_name));
 95       printf( "template_name = %s\n", template_name );
 96       printf("length of template_name = %d\n", strlen(template_name));
 97       exit(4);
 98   }
 99   if ( n_overflow < 0 )
100   {
101       printf( "An error occurred while handling your input; file: %s, line:%d\n", __FILE__, __LINE__);
102       exit(1);
103   }

outputs the following:

Compiling template file ABAQUS_Version_5.template
That template name is too large; try a smaller template name
n_overflow = 18
header_file_name = ABAQUS_Version_5.h
length of header_file_name = 18
template_name = ABAQUS_Version_5
length of template_name = 16
*** Error code 4
clearmake: Error: Build script failed for "ABAQUS_Version_5.o"

What makes it so confusing is that my dest (header_file_name) has a length, and even has data in it after the snprintf() call, and my src (template_name) also has a length and is not NULL. I've probably just made some gaff in my code, or I don't really understand snprintf(), and have been starring at it for too long. Any assistance will be greatly appreciated!

1
  • 1
    It's performing as documented. Check the man page. Commented Apr 29, 2015 at 0:23

1 Answer 1

4

That's what snprintf is supposed to do.

From man snprintf on an Ubuntu system: (emphasis added)

The functions snprintf() and vsnprintf() do not write more than size bytes (including the terminating null byte ('\0')). If the output was truncated due to this limit then the return value is the number of characters (excluding the terminating null byte) which would have been written to the final string if enough space had been available. Thus, a return value of size or more means that the output was truncated.

Or, the even simpler wording from Posix:

Upon successful completion, the snprintf() function shall return the number of bytes that would be written to s had n been sufficiently large excluding the terminating null byte.

Sign up to request clarification or add additional context in comments.

5 Comments

I must have misunderstood. I thought that it would return 0 on successful printing to the buffer, -1 if it failed, and a positive number reflecting the amount of space the buffer would need to hold the rest of the data in the src buffer. Am I wrong?
@Makenbaccon: Two definitive references provided.
I'm sorry for wasting your time. I looked through them and see where I misread. Thank you very much for your time and explanation.
So to check success, I should be comparing the return of snprintf() with the value of strlen(src) + the number of not format characters in fmt. Correct? I just want to make sure my understanding is right this time.
@Makenbaccon: You should check that the return value is not negative and that it is less than the size argument you passed to snprintf. That's what the GNU manpage suggests, in the last sentence. Usually, you would use the return value to reallocate the buffer before trying again.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.