私はこのようなコードを持っています:私はログを二度割り当てました、最初の&ログの潜在的なメモリリークはありますか?asprintf():ポインタを解放する方法は?
char *log = NULL;
asprintf(&log, "Hello: %s", name);
if (known_person== true){
asprintf(&log, "%s, %s", log, ", my old friend.");
}
free (log);
私はこのようなコードを持っています:私はログを二度割り当てました、最初の&ログの潜在的なメモリリークはありますか?asprintf():ポインタを解放する方法は?
char *log = NULL;
asprintf(&log, "Hello: %s", name);
if (known_person== true){
asprintf(&log, "%s, %s", log, ", my old friend.");
}
free (log);
はい、asprintf
は前のポインタをチェックしたり、再利用しようとしたりしないため、コードがリークします。したがって、メモリは単に失われます。あなたの例では、問題を回避する最善の方法は、
char *log = NULL;
if (known_person== true)
asprintf(&log, "Hello: %s, my old friend.", name);
else
asprintf(&log, "Hello: %s", name);
free (log);
としてそのようにコードを書き換えることであろう、バッファは、一度割り当てられ、正しく解放されます。
また、次の2つのポインタ
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のアプローチは、DRYの原則を完全に無視しています:https://en.wikipedia.org/wiki/Don't_repeat_yourself – alk
'asprintf()'の戻り値が 'freeログ) '? – chux
@alk真実なので、私は代わりを提供しました。皮肉なことに、代替の非反復コードは長くなり、エラーが発生しやすくなり、正しく維持するのが難しくなります。 – user3386109
はい。おそらくasprinf
は、同じメモリの場所にヒットせず、以前の呼び出しに関する知識がありません。
を使用することができます[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);
:第2(一時的な)ポインタを紹介し、この問題を解決するには
次のようになります。
#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);
はい、メモリがリークしています。最初のasprintfが作成してログへのポインタを保存した文字列が削除/消滅しました –
@MarcB: "*最初の' asprintf'が作成した文字列[...]は今削除/消滅しました* "これは正しくない、 「文字列」として割り当てられたメモリであり、依然として*割り当てられています。しかし、( 'log'に格納されているように)それへの参照はなくなりました。だから、メモリを 'free()'にすることはできません。これは通常 "メモリリーク"と呼ばれます。 – alk
@alkk:ええ、私のところに悪い句。 POINTERは死んだり消えたりしています。 –