C asprintf():如何释放指针?

C asprintf():如何释放指针?,c,linux,C,Linux,我有这样的代码:我分配了两次日志,第一个日志是否存在潜在的内存泄漏&log char *log = NULL; asprintf(&log, "Hello: %s", name); if (known_person== true){ asprintf(&log, "%s, %s", log, ", my old friend."); } free (log); 对。很可能asprinf不会命中相同的内存位置,并且不知道以前的调用。是的,代码会泄漏,因为asprinf既不

我有这样的代码:我分配了两次日志,第一个日志是否存在潜在的内存泄漏&log

char *log = NULL;
asprintf(&log, "Hello: %s", name);
if (known_person== true){
    asprintf(&log, "%s, %s", log, ", my old friend.");
}
free (log);

对。很可能
asprinf
不会命中相同的内存位置,并且不知道以前的调用。

是的,代码会泄漏,因为
asprinf
既不检查也不尝试重用以前的指针。因此,内存就会丢失。避免示例中出现问题的最佳方法是将代码重写为

char *log = NULL;
if (known_person== true)
    asprintf(&log, "Hello: %s, my old friend.", name);
else
    asprintf(&log, "Hello: %s", name);

free (log);
这样,缓冲区分配一次并正确释放

或者,您可以使用两个指针

char *temp = NULL;
asprintf(&temp, "Hello: %s", name);

char *log = NULL;
if (known_person== true) {
    asprintf(&log, "%s, my old friend.", temp);
    free( temp );
}
else {
    log = temp;
}

free (log);
是否存在[a][…]内存泄漏

当然可以

aprintf()
的第一次调用分配的内存的引用被对
aprintf()
的第二次调用覆盖,因此不再有机会
free()
第一次分配的内存,它“泄漏”

要解决此问题,请引入第二个(临时)指针:

解决此问题的另一种可能更便宜的方法(在编译时处理某些东西更快,但运行时更快)如下所示:

#define FORMAT_STR "Hello: %s"
#define FORMAT_SUFFIX_STR ", my old friend."

...

char name[] = "C";
char * log = NULL;

{
  char format[sizeof FORMAT_STR""FORMAT_SUFFIX_STR + 1] = FORMAT_STR;

  if (known_person == true)
  {
    strcat(format, FORMAT_SUFFIX_STR);
  }

  asprintf(&log, format, name);
}

/* Use log. */

free(log);
#define FORMAT_STR "Hello: %s"
#define FORMAT_SUFFIX_STR ", my old friend."

...

char name[] = "C";
char * log = NULL;

{
  char format[sizeof FORMAT_STR""FORMAT_SUFFIX_STR + 1] = FORMAT_STR;

  if (known_person == true)
  {
    strcat(format, FORMAT_SUFFIX_STR);
  }

  {
    int s = snprintf(NULL, 0, format, name);
    if (-1 == s) 
    {
      /* failure */
    }
    else
    {
      log = malloc(s + 1);
      if (NULL == log)
      {
        /* failure */
      }
      else
      {
        if (-1 == sprintf(log, format, name))
        {
          /* failure */
        }
      }
    }
  }
}

free(log);
在系统调用中添加错误检查将留给读者作为练习

仅使用标准C函数的第三种方法是:

解决此问题的另一种可能更便宜的方法(在编译时处理某些东西更快,但运行时更快)如下所示:

#define FORMAT_STR "Hello: %s"
#define FORMAT_SUFFIX_STR ", my old friend."

...

char name[] = "C";
char * log = NULL;

{
  char format[sizeof FORMAT_STR""FORMAT_SUFFIX_STR + 1] = FORMAT_STR;

  if (known_person == true)
  {
    strcat(format, FORMAT_SUFFIX_STR);
  }

  asprintf(&log, format, name);
}

/* Use log. */

free(log);
#define FORMAT_STR "Hello: %s"
#define FORMAT_SUFFIX_STR ", my old friend."

...

char name[] = "C";
char * log = NULL;

{
  char format[sizeof FORMAT_STR""FORMAT_SUFFIX_STR + 1] = FORMAT_STR;

  if (known_person == true)
  {
    strcat(format, FORMAT_SUFFIX_STR);
  }

  {
    int s = snprintf(NULL, 0, format, name);
    if (-1 == s) 
    {
      /* failure */
    }
    else
    {
      log = malloc(s + 1);
      if (NULL == log)
      {
        /* failure */
      }
      else
      {
        if (-1 == sprintf(log, format, name))
        {
          /* failure */
        }
      }
    }
  }
}

free(log);

是的,你在泄漏内存。第一个asprintf创建并在日志中保存指针的字符串现在被删除/gone@MarcB:“第一个
asprintf
创建的字符串[…]现在已删除/消失”这是不正确的,因为“字符串”,即已分配的内存,仍在分配。但是,对它的引用(存储在
日志
中的第一个)消失了。因此,内存不能再
free()
ed,这通常被称为“内存泄漏”。@alkk:是的,我的措辞很糟糕。指针死了/消失了。第一种方法完全忽略了DRY原则:检查
asprintf()
的返回值在
free(log)
之前不是-1有多重要?嗯,使用
intasprintf(char**strp,…
我想“如果内存分配不可能,或者发生其他错误,这些函数将返回-1,并且strp的内容未定义。”@chux Hmmm,
asprintf
不会出现在C规范中。在我正在使用的OS X上,手册页说“如果无法分配足够的空间,asprintf()和vasprintf()将返回-1并将
ret
设置为空指针。“所以我想这就是为什么不应该在可移植代码中使用非标准函数的原因。@chux解决方法是
if(asprintf(&ptr,…)