如何克服 snprintf 在不同类 UNIX 操作系统中不一致的行为?
根据手册页,snprintf 返回从 glibc 版本 2.2 开始写入的字节数。 但在较低版本的 libc2.2 和 HP-UX 上,它返回一个正整数,这可能导致缓冲区溢出。
如何克服这一问题并编写可移植的代码?
编辑:为了更清楚起见,
此代码在 lib 2.3 中完美运行,
if ( snprintf( cmd, cmdLen + 1, ". %s%s", myVar1, myVar2 ) != cmdLen )
{
fprintf( stderr, "\nError: Unable to copy bmake command!!!");
returnCode = ERR_COPY_FILENAME_FAILED;
}
它返回 Linux 上字符串 (10) 的长度。 但相同的代码返回一个大于 HP-UX 计算机上打印的字符数的正数。 希望这个解释没问题。
Per man pages, snprintf is returning number of bytes written from glibc version 2.2 onwards. But on lower versions of libc2.2 and HP-UX, it returns a positive integer, which could lead to a buffer overflow.
How can one overcome this and write portable code?
Edit : For want of more clarity
This code is working perfectly in lib 2.3
if ( snprintf( cmd, cmdLen + 1, ". %s%s", myVar1, myVar2 ) != cmdLen )
{
fprintf( stderr, "\nError: Unable to copy bmake command!!!");
returnCode = ERR_COPY_FILENAME_FAILED;
}
It returns the length of the string (10) on Linux. But the same code is returning a positive number that is greater than the number of characters printed on HP-UX machine. Hope this explanation is fine.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您可以创建一个 snprintf 包装器,当缓冲区中没有足够的空间时,它为每种情况返回 -1。
有关更多文档,请参阅手册页。 它还有一个威胁所有案件的例子。
you could create a snprintf wrapper that returns -1 for each case when there is not enough space in the buffer.
See the man page for more docs. It has also an example which threats all the cases.
您是否考虑过 printf 的可移植实现? 我不久前也在寻找一个,最后选定了三重奏。
http://daniel.haxx.se/projects/trio/
Have you considered a portable implementation of printf? I looked for one a little while ago and settled on trio.
http://daniel.haxx.se/projects/trio/
你的问题还是不清楚。 链接到的手册页这样说道:
因此,如果您想知道输出是否被截断:
Your question is still unclear. The man page linked to speaks thus:
So, if you want to know if your output was truncated:
*printf 可移植性存在很多问题,实际上您可能想遵循以下三种路径之一:
需要符合 c99 的 *printf,因为 9 年对任何人来说都足够了,只是说平台已损坏
有一个 my_snprintf() 和一堆 #ifdef,用于您想要支持所有调用下面的 vsnprintf() 的特定平台(了解最低公分母就是您所拥有的)。
只需在代码中携带一份 vsnprintf() 的副本,对于简单的用例,它实际上漂亮简单,对于其他人,您可能想查看vstr,然后您就会免费获取客户格式化程序。
...正如其他人建议的那样,您可以对 -1 情况进行黑客合并 #1 和 #2,但这是有风险的,因为 c99 *printf 在某些条件下可以/确实返回 -1。
就我个人而言,我建议使用 像 ustr 这样的字符串库,它可以为您提供简单的解决方法并免费为您提供托管字符串。 如果您真的很关心,可以与 vstr 结合使用。
There are a whole host of problems with *printf portability, and realistically you probably want to follow one of three paths:
Require a c99 compliant *printf, because 9 years should be enough for anyone, and just say the platform is broken otherwise.
Have a my_snprintf() with a bunch of #ifdef's for the specific platforms you want to support all calling the vsnprintf() underneath (understanding the lowest common denominator is what you have).
Just carry around a copy of vsnprintf() with your code, for simple usecases it's actually pretty simple and for others you'd probably want to look at vstr and you'll get customer formatters for free.
...as other people have suggested you can do a hack merging #1 and #2, just for the -1 case, but that is risky due to the fact that c99 *printf can/does return -1 in certain conditions.
Personally I'd recommend just going with a string library like ustr, which does the simple workarounds for you and gives you managed strings for free. If you really care you can combine with vstr.
我找到了一种可移植的方法来预测和/或限制 sprintf 和相关函数返回的字符数,但它效率低下,而且许多人认为它不优雅。
您要做的就是使用 tmpfile()、fprintf() 创建一个临时文件(可靠地返回写入的字节数),然后倒带并将全部或部分文本读入缓冲区。
例子:
I have found one portable way to predict and/or limit the number of characters returned by sprintf and related functions, but it's inefficient and many consider it inelegant.
What you do is create a temporary file with tmpfile(), fprintf() to that (which reliably returns the number of bytes written), then rewind and read all or part of the text into a buffer.
Example:
请使用更高级的 asprintf() 来代替。
它是一个 GNU 扩展,但如果它本身不可用,则值得将其复制到目标平台。
Use the much superior asprintf() instead.
It's a GNU extension, but it's worth copying to the target platform in the event that it's not natively available.