下面是摘自“ 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);
}
答案 0 :(得分:3)
让我们仔细看看这两行:
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
不释放任何非空指针,也可能是内存泄漏。