使用没有手动分配缓冲区的sprintf

时间:2008-11-17 06:38:45

标签: c++ c string memory

在我正在处理的应用程序中,日志记录工具使用sprintf来格式化写入文件的文本。所以,像:

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

当发送的消息对于手动分配的缓冲区而言变得太大时,这有时会导致问题。

有没有办法获得sprintf行为,而无需像这样手动分配内存?

编辑:虽然sprintf是一个C操作,我正在寻找C ++类型的解决方案(如果有的话!)让我得到这种行为...

5 个答案:

答案 0 :(得分:18)

您可以使用asprintf(3)(注意:非标准)为您分配缓冲区,因此您无需预先分配它。

答案 1 :(得分:10)

不,你不能使用sprintf()来分配足够的内存。替代方案包括:

  • 使用snprintf()截断消息 - 不能完全解决您的问题,但可以防止缓冲区溢出问题
  • 双倍(或三倍或......)缓冲区 - 除非您处于受限制的环境中
  • 使用C ++ std::stringostringstream - 但您将丢失printf格式,您必须使用<<操作
  • 使用类似printf的%运算符
  • 附带的Boost Format

答案 2 :(得分:5)

我也不知道避免分配的版本,但是如果C99 sprintfs允许作为字符串的NULL指针。效率不高,但这会给你完整的字符串(只要有足够的内存可用)而不会有溢出的风险:

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

答案 3 :(得分:3)

“日志记录工具使用sprintf来格式化写入文件的文本”

fprintf()不会施加任何大小限制。如果您可以直接将文本写入文件,请执行此操作!

然而,我假设有一些中间处理步骤。如果您知道需要多少空间,可以使用malloc()分配那么多空间。

有时这样的一种技术是分配一个合理大小的缓冲区(99%的时间都足够大),如果它不够大,可以将数据分成一个一个一个地处理的块。

答案 4 :(得分:1)

使用spillaf的vanilla版本,无法阻止数据覆盖传入的缓冲区。无论在堆栈上手动分配或分配内存,都是如此。

为了防止缓冲区被覆盖,你需要使用一个更安全的sprintf版本,比如sprintf_s(仅限windows)

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