我的代码是这样的:我分配了两次日志,第一个& log是否存在潜在的内存泄漏?
char *log = NULL;
asprintf(&log, "Hello: %s", name);
if (known_person== true){
asprintf(&log, "%s, %s", log, ", my old friend.");
}
free (log);
答案 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
不会触及相同的内存位置,也不会知道以前的调用。