tl; dr可以asprintf
天真地用于连接而无需调用临时指针?
asprintf
GNU引入并在其他几个clib实现中采用的函数是使用类似方案在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);
Run Code Online (Sandbox Code Playgroud)
当包裹在主要和必要的包含,这对我来说运行良好.
是否在整个地方泄漏记忆?Valgrind说它在我的盒子上.这是一个错误吗?
我面前的那个人页说
asprintf()和vasprintf()函数将*ret设置为指向缓冲区的指针,该缓冲区足以容纳格式化的字符串.应该将此指针传递给free(3)以在不再需要时释放已分配的存储.如果无法分配足够的空间,asprintf()和vasprintf()将返回-1并将ret设置为NULL指针.
在这句话中由于缺少"设置*ret
为指向一个新的缓冲[...]",我很想假设函数使用realloc
的getline
一样.
使用签名int asprintf(char **ret, const char *format, ...);
具体.
asprintf
跑得太快realloc
了.
想象一下,我们实现了这个函数,我们可以realloc(*ret)
在它取消引用其中一个混淆原始缓冲区的变量之前运行.该缓冲区已被释放,这在技术上是未定义的行为.这将代表一个错误.
asprintf
在读取之前写入缓冲区.在上面的代码就可以成像功能拷贝的内容argv[1]
到*ret
之前的每va_arg
对str
参数.我引用的联机帮助页似乎并不排除这种情况.
asprintf
不free *ret
直接或通过使用realloc
.这将避免问题编号(1),但如果如上所述使用会泄漏内存.再一次,该手册页似乎不排除它.
通过将单个调用替换为asprintf
with,可以避免上述所有操作
{
char *newStr = NULL;
asprintf(newStr,"%s %s",argv[i],str);
free(str);
str = newStr;
}
Run Code Online (Sandbox Code Playgroud)
但这很笨重.
共识实现是否保证第一个代码示例是安全和正确的?
小智 3
是否到处都在泄漏内存?
是的,它确实。
char *str = strdup(argv[i]);
Run Code Online (Sandbox Code Playgroud)
这里,str
包含一个指向 ated 内存的指针malloc()
,应该是free()
d。
asprintf(&str, "%s %s", argv[i], str);
Run Code Online (Sandbox Code Playgroud)
此处,asprintf()
进行修改str
,使其指向函数本身分配的其他内存。现在你刚刚丢失了指向 ped 字符串的指针strdup()
,因此发生了泄漏。