下面是摘自“21 世纪 C”的片段。 如果我在宏 Sasprintf 中使用 free(tmp_string_for_extend) 而不是 free(write_to) 释放内存,我无法弄清楚为什么程序的结果如此不同。谢谢,
#define Sasprintf(write_to, ...) { \
char *tmp_string_for_extend = (write_to); \
asprintf(&(write_to), __VA_ARGS__); \
free(tmp_string_for_extend); \
}
int main() {
inti = 3;
char *q = NULL;
Sasprintf(q,"select * from tab");
Sasprintf(q,"%s where col%i is not null",q,i);
printf("%s\n",q);
}
最佳答案
让我们仔细看看这两行:
char *q=NULL;
Sasprintf(q,"select * from tab");
如果我们扩展宏,它将变成(大致):
char *q=NULL;
{
char *tmp_string_for_extend = (q);
asprintf(&(q), "select * from tab");
free(tmp_string_for_extend);
}
应该很清楚,tmp_string_for_extend
的初始化将等同于将其初始化为NULL
,因为此时q
是NULL
。
因此,当您调用 free(tmp_string_for_extend)
时,您实际上是在执行 free(NULL)
。使用空指针调用 free
没有任何作用。
如果您改为在宏中执行 free((write_to))
那么它将扩展为 free((q))
这将释放您刚刚分配的内存使用 asprintf
。之后取消引用 q
(打印内容时发生)将导致 undefined behavior .
你应该调用 free(q)
在你完成 q
之后。
另请注意,对于大多数 sprintf
变体,可能包括 GNU libc 特定的 asprintf
函数,对源(作为参数)和目标使用相同的参数通常也是未定义的行为。这使您的第二个宏调用无效。即使定义了它,如果 asprintf
没有释放任何非空指针,它也可能是内存泄漏。
关于c - asprintf() 释放内存的技巧是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52853017/