安全 printf 到字符串的最佳方法?
有谁知道将 printf 样式函数的输出重定向到字符串的安全好方法? 显而易见的方法会导致缓冲区溢出。
比如:
string s;
output.beginRedirect( s ); // redirect output to s
... output.print( "%s%d", foo, bar );
output.endRedirect();
我认为这个问题与问“将打印多少个字符?”是一样的。 有想法吗?
Does anyone know a good safe way to redirect the output of a printf-style function to a string? The obvious ways result in buffer overflows.
Something like:
string s;
output.beginRedirect( s ); // redirect output to s
... output.print( "%s%d", foo, bar );
output.endRedirect();
I think the problem is the same as asking, "how many characters will print produce?"
Ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
您可以使用:
std::format
:基于fmt::format
,这是最安全的标准APIsnprintf
如果您正在使用char*
- 这可以帮助避免缓冲区溢出,但类型不安全std::stringstream
如果您想使用字符串(与 printf 不同,但允许您使用普通流函数轻松操作字符串)。boost::format
< /a> 如果您想要一个类似于 printf 且可以处理流的函数。 (根据评论中的贾尔夫)You can use:
std::format
: based onfmt::format
, this is the safest standard APIsnprintf
if you are working with achar*
- this can help avoid buffer overflow but not type safestd::stringstream
if you want to use strings (not same as printf but will allow you to easily manipulate the string using the normal stream functions).boost::format
if you want a function similar to printf that will work with streams. (as per jalf in comments){fmt} 库 提供了安全的
printf
实现。 例如,fmt::sprintf
格式化并返回std::string
:如果您可以使用稍微不同的格式字符串语法,您也可以使用 C++20 < a href="https://en.cppreference.com/w/cpp/utility/format/format" rel="nofollow noreferrer">
std::format
:免责声明:我是 {fmt} 和 C++20 std::format 的作者。
The {fmt} library provides a safe
printf
implementation. For example,fmt::sprintf
formats and returns astd::string
:If you are OK with a slightly different format string syntax you could also use C++20
std::format
:Disclaimer: I'm the author of {fmt} and C++20 std::format.
snprintf()
函数打印到一个字符串,但只打印给定的长度。可能就是您正在寻找的...
The
snprintf()
function prints to a string, but only as much as the length given to it.Might be what you're looking for...
由于您已将其标记为 C++(而不仅仅是 C),我将指出在 C++ 中执行此类操作的典型方法是使用 stringstream,而不是 printf 系列。 无需担心字符串流的缓冲区溢出。
如果您愿意,也可以使用 Boost Format 库printf 风格的格式字符串,但想要更安全的东西。
Since you've tagged this as C++ (rather than just C), I'll point out that the typical way to do this sort of thing in C++ is to use stringstream, not the printf family. No need to worry about buffer overflows with stringstreams.
The Boost Format library is also available if you like printf-style format strings but want something safer.
snprintf() 返回写入整个字符串所需的字节数。
因此,作为一个小例子:
输出:
snprintf() returns the number of bytes needed to write the whole string.
So, as a tiny example:
output:
此 StackOverflow 问题类似的讨论。 同样在这个问题中,我提出了我最喜欢的解决方案,一个“格式”函数,它采用与 printf 相同的参数并返回 std::string 。
This StackOverflow question has a similar discussion. Also in that question I present my favorite solution, a "format" function that takes identical arguments to printf and returns a std::string.
老派:
允许您对写入的数量进行限制,并返回实际写入的大小,并
分配(使用
malloc()
)足够的缓冲区,然后这将成为您的问题free( )
。 `asprintf 是一个 GNU libc 函数,现在在 BSD libc 中重新实现。Old school:
allows you to put a limit on the number written, and return the actual written size, and
allocate (with
malloc()
) a sufficient buffer which then becomes your problem tofree()
. `asprintf is a GNU libc function now reimplemented in the BSD libc.使用 C99,您可以使用 snprintf 函数,它将缓冲区的大小作为参数。 GNU C 库有 asprintf,它为您分配一个缓冲区。 但对于 C++,您可能最好使用 iostream。
维基百科有更多信息。
With C99 you have the snprintf-function which takes the size of the buffer as a parameter. The GNU C-library has asprintf which allocates a buffer for you. For c++ though, you might be better of using iostream.
Wikipedia has more info.
我发现 printf 格式非常有用,并且比流更容易使用。 另一方面,我也非常喜欢 std::string 。 解决方案是使用 sprintf,但它无法处理任意缓冲区大小。
我发现我需要处理常见情况(例如,缓冲区限制为 256 个字符),无需处理
开销,但仍安全地处理大缓冲区。 为此,我在班级中作为成员分配了一个 256 个字符的缓冲区,并使用 snprinf 传递该缓冲区及其大小。 如果 snprintf 成功,我可以立即返回格式化的字符串。 如果失败,我分配缓冲区并再次调用 snprinf。 缓冲区在类的析构函数中被释放。
I find the printf formatting to be very helpful and easier to use than streams. On the other hand, I do like std::string a lot too. The solution is to use sprintf, but that cannot handle arbitrary buffer size.
I've found that I need to handle common case (say, buffer limited to 256 chars) w/o
overhead, and yet handle the large buffer safely. To do that, I have a buffer of 256 chars alocated in my class as a member, and I use snprinf, passing that buffer and its size. If snprintf succeeds, I can immediately retunr the formatted string. If it fails, I allocate the buffer and call snprinf again. The buffer is deallocated in the class' destructor.
在 Windows 上:
来自
strsafe.h/lib
。On Windows:
from
strsafe.h/lib
.Microsoft 引入了“安全”crt 函数这。
您可以使用 printf_s()
Microsoft introduce the 'safe' crt functions for this.
You could use printf_s()