gpt4 book ai didi

c - 你如何安全地调用 vsnprintf()?

转载 作者:太空狗 更新时间:2023-10-29 15:15:51 25 4
gpt4 key购买 nike

我正在将一些非常古老(> 10y)的 C 代码移植到现代 Linux。我在自定义编写的 vsnprintf() 包装器中遇到了段错误(显然它的任务是检测重复的输出字符串并保留它们):

char* strVPrintf(const String fmt, va_list ap)
{
/* Guess we need no more than 50 bytes. */
int n, size = 50;
char* p = (char*)memMalloc(size), q;

while (1) {
/* Try to print in the allocated space. */
n = vsnprintf(p, size, fmt, ap);
/* If that worked, return the string. */
if (n > -1 && n < size) {
break;
}
/* Else try again with more space. */
if (n > -1) /* glibc 2.1 */
size = n + 1; /* precisely what is needed */
else /* glibc 2.0 */
size *= 2; /* twice the old size */
p = memRealloc(p, size);
}

q = strRegister(p);
memFree(p);
return q;
}

作者似乎假设标准 vsnprintf() 函数返回写入的字符数,如果没有足够的空间来格式化所有参数,则简单地返回一个标记值。这意味着您可以猜测缓冲区大小并在必要时增加它。

但是在我的系统(Ubuntu 14.04、glibc 2.19)上,当调用 vnprintf 时为提供的空间使用太多参数时会导致段错误。 snprintf() 系列的语义在此期间发生了巨大的变化吗?确保提供足够缓冲空间的现代方法是什么?

最佳答案

这是在除 SunOS 4(已过时 20 年)之外的所有操作系统上使用 snprintfvsnprintf 的正确方法,因此您的问题出在其他地方.

我会做一个纯粹的猜测并说我几乎可以肯定你的问题是你将 va_list ap 传递给 vsnprintf 消耗它并且那么你希望它在下次调用时被重置。这是不正确的,并且多年前就已在 gcc 中停止工作(因为它只在某些架构上工作)。

改变:

n = vsnprintf(p, size, fmt, ap);

收件人:

va_list apc;
va_copy(apc, ap);
n = vsnprintf(p, size, fmt, apc);
va_end(apc);

看看是否有帮助。

下面是一个简单的测试,看看发生了什么:

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

void
foo(const char *fmt, va_list ap)
{
#ifdef BAD
vprintf(fmt, ap);
#else
va_list apc;
va_copy(apc, ap);
vprintf(fmt, apc);
va_end(apc);
#endif
vprintf(fmt, ap);
}

void
bar(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
foo(fmt, ap);
va_end(ap);
}

int
main(int argc, char **argv)
{
bar("foo %s\n", "bar");
return 0;
}

运行时我得到这个:

$ cc -o foo foo.c && ./foo
foo bar
foo bar
$ cc -DBAD -o foo foo.c && ./foo
foo bar
foo ����

关于c - 你如何安全地调用 vsnprintf()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37788305/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com