asprintf():如何释放指针?

时间:2015-09-04 20:25:06

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

3 个答案:

答案 0 :(得分:7)

是的,代码会泄漏,因为asprintf既没有检查也没有尝试重用前一个指针。因此,记忆就丢失了。在您的示例中避免此问题的最佳方法是将代码重写为

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);

答案 1 :(得分:2)

  

有[a] [...]内存泄漏

肯定是的。

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

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

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

{
  char * log_tmp = NULL;

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

/* 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);
  }

  asprintf(&log, format, name);
}

/* Use log. */

free(log);

添加对系统调用的错误检查留给读者作为练习。

仅使用标准C功能的第三种方法是:

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

{
  char * log_tmp = NULL;

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

/* 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);

答案 2 :(得分:0)

是。可能asprinf不会触及相同的内存位置,也不会知道以前的调用。