c - 使用 vsnprintf 时有没有办法绕过 va_copy?
问题描述
我在一个旧的嵌入式平台上引入了一个 3rd 方协议栈,除了 va_copy 之外,所有的 va_* 东西都被实现了。我面临的问题是,在第 3 方堆栈中,使用了 vsnprintf():
int fun(char **buf, size_t buf_size, const char *fmt, va_list ap) {
va_list ap_copy;
int len;
/* first call*/
va_copy(ap_copy, ap);
len = vsnprintf(*buf, buf_size, fmt, ap_copy);
va_end(ap_copy);
if(len >= buf_size)
{
/* 2nd call*/
va_copy(ap_copy, ap);
len = vsnprintf(*buf, len + 1, fmt, ap_copy);
va_end(ap_copy);
}
}
幸运的是,第 3 方堆栈证明了它自己的 vsnprintf 函数(称为 new_vsnprintf),但没有 va_copy,只有第一个调用有效,即当 len 小于 buf_size 时。以下是我的称呼:
#define vsnprintf new_vsnprintf
int fun(char **buf, size_t buf_size, const char *fmt, va_list ap) {
//va_list ap_copy;
int len;
/* first call*/
va_start(ap, fmt);
len = vsnprintf(*buf, buf_size, fmt, ap);
va_end(ap);
if(len >= buf_size)
{
/* 2nd call*/
va_start(ap, fmt);
len = vsnprintf(*buf, len + 1, fmt, ap); //new_vsnprintf()
va_end(ap);
}
}
当尝试通过va_arg()
. 我假设 (va_list) ap 的内部指针指向错误的内存地址。那么如何纠正呢?
解决方案
你不应该在你的 function中调用va_start
任何一个。它们只能在参数列表中具有指示参数数量可变的函数中调用。如果我尝试编译当前存在的代码,我的 gcc (4.8.4) 版本甚至会引发错误。va_end
fun
...
test.c: In function ‘fun’:
test.c:14:3: error: ‘va_start’ used in function with fixed args
va_start(ap, fmt);
似乎在具有固定参数的函数中调用它们会导致未定义的行为,幸运的是第一次调用vsnprintf
实际上是有效的。
由于您没有va_arg
在内部调用不应该改变fun
的值,ap
因此您应该能够根据需要调用任意vsnprintf
多次。
推荐阅读
- git - `git log -- file` 没有显示任何内容
- json - 如何将此 WordPress JSON 条目转换为 PHP 数组?
- angular - 如何在angular6中从外部应用程序根调用方法
- rdkit - 有没有办法显示 rdkit.Chem.rdmolops.GetAdjacencyMatrix 中的原子索引?
- r - 如何用 igraph 制作星图?
- c# - Service Fabric 错误:“服务不存在”
- python - 在 Flask 中,如何发送临时文件并在上传完成后将其删除?
- python - 如何使用 pandas 数据框迭代和修改行值
- linq - 使用 linq 简化嵌套 for 循环
- c# - 如何将视图模型的属性绑定到用作项控件源的集合项的属性