C++ 在没有手动分配缓冲区的情况下使用sprintf

C++ 在没有手动分配缓冲区的情况下使用sprintf,c++,c,string,memory,C++,C,String,Memory,在我正在开发的应用程序中,日志记录工具使用sprintf格式化写入文件的文本。比如说: char buffer[512]; sprintf(buffer, ... ); 当发送的消息对于手动分配的缓冲区来说太大时,这有时会导致问题 有没有一种方法可以在不需要像这样手动分配内存的情况下获得sprintf的行为 编辑:虽然代码> SpaTFF 是C操作,但我正在寻找C++类型的解决方案(如果有的话),我可以得到这种行为… < P>日志设备使用SAMTIFF格式化写入文件的文本“” fprintf(

在我正在开发的应用程序中,日志记录工具使用
sprintf
格式化写入文件的文本。比如说:

char buffer[512];
sprintf(buffer, ... );
当发送的消息对于手动分配的缓冲区来说太大时,这有时会导致问题

有没有一种方法可以在不需要像这样手动分配内存的情况下获得sprintf的行为

<>编辑:虽然代码> SpaTFF 是C操作,但我正在寻找C++类型的解决方案(如果有的话),我可以得到这种行为…

< P>日志设备使用SAMTIFF格式化写入文件的文本“

fprintf()
不施加任何大小限制。如果可以将文本直接写入文件,请这样做

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


有时,一种技术是分配一个合理大小的缓冲区(在99%的时间内都足够大),如果缓冲区不够大,则将数据分成块,然后逐个处理。

对于普通版本的sprintf,无法防止数据覆盖传入的缓冲区。无论是手动分配内存还是在堆栈上分配内存,这都是正确的

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


不,您不能使用
sprintf()
来分配足够的内存。备选方案包括:

  • 使用
    snprintf()
    截断消息-不能完全解决问题,但可以防止缓冲区溢出问题
  • 两倍(或三倍或…)缓冲区-除非您处于受限环境中

  • 使用C++ >代码> STD::String 和 OSTRIGSTROMUST/CODE> >但是你将丢失PrtTf格式,你必须使用

    你可以使用AsPrTFF(3)(注:非标准)来分配缓冲区,这样你就不需要预先分配它。

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

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

    请提及此函数在不同系统中的可用性,因为它既不是标准的C库也不是POSIX。它主要是Linux—可能也是BSD。还有一个vasprintf()。哦,是的,很抱歉。。。OP没有提到哪个站台,所以我把它扔了出去。它可以在Linux、BSD和Mac OS X上找到。。。它现在是gnuc库的标准部分。请注意,snprintf()告诉您需要多少空间,因此如果需要,您可以使用它两次,第一次使用如图所示的静态缓冲区,第二次使用动态分配的缓冲区。-1表示第二个建议(将缓冲区大小增加一倍。由于您不知道最大字符串长度,因此无法保证它不会溢出,即使您将其乘以10亿)。如果您使用C99,也可以使用可变长度数组,因此不使用mallocing str,只需将其声明为“char str[length+1];”调用snprintf后。无需取消分配它,因为它位于堆栈上。如果使用MSVC运行时,您会发现snprintf返回的是负值,而不是所需的长度。因此,如果您希望在MSVC下获得所需的长度,则需要使用另一个函数,\u vscprintf[文件访问比内存访问慢得多。这就是为什么中间sprintf不是一个坏主意的原因之一。在可用的情况下,您可以通过缓冲文件来获得大部分好处。仍然存在调用开销,但至少不会影响磁盘。使用普通的sprintf()可以防止缓冲区溢出,例如sprintf(buf,“%.*s”,buf_size-1,input_字符串);但这仅适用于已知的固定格式字符串。