gpt4 book ai didi

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

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

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);

当包裹在一个 main 和必要的 include 中时,这对我来说运行良好。

但是……

它是否到处都在泄漏内存? Valgrind 说它在我的盒子上。这是错误吗?

我面前的手册页说

The asprintf() and vasprintf() functions set *ret to be a pointer to a buffer sufficiently large to hold the formatted string. This pointer should be passed to free(3) to release the allocated storage when it is no longer needed. If sufficient space cannot be allocated, asprintf() and vasprintf() will return -1 and set ret to be a NULL pointer.

在短语“set *ret to be a pointer to a new buffer [...]” 的情况下,我很想假设该函数正在像 getline 那样使用 realloc

可能是什么问题?

为了具体性,使用签名 int asprintf(char **ret, const char *format, ...);

  1. asprintf 过早运行 realloc

    想象一下,我们以这样一种方式实现该函数,以至于我们可以在它取消引用给原始缓冲区起别名的可变参数之一之前运行 realloc(*ret)。该缓冲区已被释放,这在技术上是未定义的行为。这将代表一个错误。

  2. asprintf 在读取之前写入缓冲区。在上面的代码中,我们可以想象将 argv[1] 的内容复制到 *ret 中的函数,在 上的每个 va_arg 之前str 参数。我引用的联机帮助页似乎并未排除这种情况。

  3. asprintf 不会直接或通过使用 realloc free *ret。这将避免问题编号 (1),但如果按上述方式使用会泄漏内存。该手册页似乎也没有排除这种可能性。

解决方法

可以通过将对 asprintf 的单个调用替换为

来避免上述所有情况
{
char *newStr = NULL;
asprintf(newStr,"%s %s",argv[i],str);
free(str);
str = newStr;
}

但这很笨重。

共识实现是否保证第一个代码示例是安全和正确的?

最佳答案

Is it leaking memory all over the place?

是的,确实如此。

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

这里,str 包含一个指向 malloc() 的内存指针,它应该是 free()d。

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

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

关于c - 让 asprintf 使用同时也是输入的非 NULL 目标指针是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15645027/

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