Using sprintf without a manually allocated buffer

2020-06-16 03:04发布

问题:

In the application that I am working on, the logging facility makes use of sprintf to format the text that gets written to file. So, something like:

char buffer[512];
sprintf(buffer, ... );

This sometimes causes problems when the message that gets sent in becomes too big for the manually allocated buffer.

Is there a way to get sprintf behaviour without having to manually allocate memory like this?

EDIT: while sprintf is a C operation, I'm looking for C++ type solutions (if there are any!) for me to get this sort of behaviour...

回答1:

No you can't use sprintf() to allocate enough memory. Alternatives include:

  • use snprintf() to truncate the message - does not fully resolve your problem, but prevent the buffer overflow issue
  • double (or triple or ...) the buffer - unless you're in a constrained environment
  • use C++ std::string and ostringstream - but you'll lose the printf format, you'll have to use the << operator
  • use Boost Format that comes with a printf-like % operator


回答2:

You can use asprintf(3) (note: non-standard) which allocates the buffer for you so you don't need to pre-allocate it.



回答3:

I dont also know a version wich avoids allocation, but if C99 sprintfs allows as string the NULL pointer. Not very efficient, but this would give you the complete string (as long as enough memory is available) without risking overflow:

length = snprintf(NULL, ...);
str = malloc(length+1);
snprintf(str, ...);


回答4:

"the logging facility makes use of sprintf to format the text that gets written to file"

fprintf() does not impose any size limit. If you can write the text directly to file, do so!

I assume there is some intermediate processing step, however. If you know how much space you need, you can use malloc() to allocate that much space.

One technique at times like these is to allocate a reasonable-size buffer (that will be large enough 99% of the time) and if it's not big enough, break the data into chunks that you process one by one.



回答5:

With the vanilla version of sprintf, there is no way to prevent the data from overwriting the passed in buffer. This is true regardless of wether the memory was manually allocated or allocated on the stack.

In order to prevent the buffer from being overwritten you'll need to use one of the more secure versions of sprintf like sprintf_s (windows only)

http://msdn.microsoft.com/en-us/library/ybk95axf.aspx