让asprintf使用也是输入的非NULL目标指针是否安全?

时间:2013-03-26 18:46:44

标签: c alias stdio

tl; dr 如果不调用临时指针,可以天真地使用asprintf进行连接吗?


GNU引入并在其他几个clib实现中采用的函数asprintf是一个诱人的解决方案,可以使用像

这样的方案在c中进行任意连接
int i=0;
char *str = strdup(argv[i]);
while (argv[++i]) {
   asprintf(&str,"%s %s",argv[i],str);   // <=== This line
}
asprintf(&str,"%s\n",str);

当包裹在主要和必要的包含中时,这对我来说运行正常。

但是...

它是否在整个地方泄漏了内存? Valgrind说它在我的盒子上。这是一个错误吗?

我面前的男人页面说

  

asprintf()和vasprintf()函数将* ret设置为指向a的指针        缓冲区足够大以容纳格式化的字符串。这个指针        应该传递给free(3)以释放分配的存储空间        不再需要。如果无法分配足够的空间,asprintf()        和vasprintf()将返回-1并将ret设置为NULL指针。

由于短语“将*ret设为指向缓冲区[...]”的指针,我很想参加假设该函数使用realloc作为getline

可能有什么问题?

使用签名int asprintf(char **ret, const char *format, ...);来实现具体性。

  1. asprintf过早运行realloc

    想象一下,我们实现了这个函数,我们可以运行realloc(*ret),然后取消引用其中一个混淆原始缓冲区的变量。该缓冲区已被释放,这在技术上是未定义的行为。这将代表一个错误。

  2. asprintf在读取之前写入缓冲区。在上面的代码中,我们可以将argv[1]的内容复制到*ret va_arg str asprintf之前的函数。我引用的联合页面似乎并没有统治这种情况。

  3. free *ret不会realloc直接或通过使用asprintf。这将避免问题编号(1),但如果如上所述使用会泄漏内存。同样,该手册页似乎不排除它。

  4. 解决方法

    使用

    替换单{ char *newStr = NULL; asprintf(newStr,"%s %s",argv[i],str); free(str); str = newStr; } 次呼叫可以避免上述所有情况
    {{1}}

    但这很笨重。

    协商一致实施是否保证第一个代码示例安全无误?

1 个答案:

答案 0 :(得分:3)

  

它是否在整个地方泄漏记忆?

是的,确实如此。

char *str = strdup(argv[i]);

此处,str包含指向malloc()内存的指针,该内存应为free() d。

asprintf(&str, "%s %s", argv[i], str);

这里,asprintf()修改str,使其指向函数本身分配的其他内存。现在你丢失了指向strdup() ped字符串的指针,因此泄漏了。