【发布时间】:2016-11-25 16:45:56
【问题描述】:
我正在开发 AVR 平台。 avr-libc 不提供asprintf()。我试图引入我的项目的库需要它。有用的是,同一个库包含一个实现(如下)。不幸的是,它提供了奇怪的结果。具体来说,我确定vsnprintf() 的返回码永远不会正确;在连续调用时,我似乎总是看到相同的错误值(5、1 等),而不是随机结果。
对该函数的调用是:asprintf(&str, "%s[%d]", name, val);。 str 是调用函数内堆栈上的 char*。 name 是一个简单的短文本描述符,我已验证它不为空且长度不为零。 val 是一个简单的索引,在调用asprintf() 的循环中递增。此调用生成的结果字符串应为 7 个字符长(不包括空终止符)。 asprintf() 在整个库中被调用。我对包含库的使用只在这个单个循环中执行它(两次)。如果我删除此调用并用虚拟值替换结果,该库会按预期工作。在 asprintf() 的实现中将缓冲区分配给取消引用的 ret 指针时,执行似乎崩溃了。
尽管对缓冲区、指针取消引用和管理 var args 进行了大量实验,但我无法让此函数正常运行。然而,在 OS X 上交叉编译它工作得很好。
我知道vsnprintf() 的行为不一定在所有平台上都相同。也就是说,据我所知,这种用法应该可以按预期工作。
有什么想法吗?它可能是函数本身之外的东西吗?某种导致问题的 stdio 初始化或链接器库选项?
int asprintf(char **ret, const char *fmt, ...) {
va_list ap1;
va_list ap2;
int count;
va_start(ap1, fmt);
va_copy(ap2, ap1);
count = vsnprintf(NULL, 0, fmt, ap1);
va_end(ap1);
if(count > 0) {
char* buffer;
if (!(buffer = (char*)malloc(count+1))) {
return -1;
}
count = vsnprintf(buffer, count+1, fmt, ap2);
*ret = buffer;
}
va_end(ap2);
return count;
}
【问题讨论】:
-
progression of incorrect values (5, 1, etc.) upon successive calls这些连续调用的输入是什么?如果您显示实际的asprintf呼叫,它会有所帮助。 -
好点。更新了问题以描述如何调用此函数。
-
是否在两个实现或调用它的模块包含的标头中声明了
asprintf(使用正确的原型)? -
@dxiv 我不得不挖掘一点。不,我在 any 标头中找不到使用原型声明的
asprintf()。在缺少此功能的平台上的构建中包含此功能的方法也没有扩展到相应头文件中的原型。当我将原型声明在它应该在的位置时,你瞧,错误消失了。您能否解释一下是什么触发了您认为这是可能的问题的想法?如果没有适当的原型,代码会在处理 var args 时破坏内存吗? -
很有可能会破坏堆栈。