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

标签 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);
}

最佳答案

让我们仔细看看这两行:

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 没有释放任何非空指针,它也可能是内存泄漏。

关于c - asprintf() 释放内存的技巧是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52853017/

相关文章:

c - 在c中使用删除函数

c char 指针赋值

c - 在 C 中读取可变长度的字符串用户输入

C - 出现错误 *** 检测到堆栈粉碎 ***

c - 在简单的 gtk 按键事件示例中,GDK_SHIFT_MASK 似乎被忽略了

如果值为负数,Linux 的 C 不会返回

c - 如何使用按位 C 运算找到 0x87654321 的补码?

c - 多次 Recv 调用 Socket C 编程

c++ - 找不到 Sphinx Ubuntu 14 c++ sphinx_config.h

c - getchar() 和标准输入