asprintf()释放内存的技巧是什么?

时间:2018-10-17 10:43:33

标签: c

下面是摘自“ 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);
}

1 个答案:

答案 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,因为此时的qNULL

因此,当您致电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不释放任何非空指针,也可能是内存泄漏。