web-dev-qa-db-ja.com

返された変数のメモリを解放する適切な方法

ユーザー入力を取得するように設計された関数を作成しました。ユーザー入力を保持する変数にメモリを割り当てる必要があります。ただし、その変数は関数の最後に返されます。割り当てられたメモリを解放する/変数の値を返す適切な方法は何ですか?

これがコードです:

char *input = malloc(MAX_SIZE*sizeof(char*));
int i = 0;
char c;

while((c = getchar()) != '\n' && c != EOF) {
    input[i++] = c;
}

return input;

入力のアドレスを返して、使用後に解放する必要がありますか?

入力変数を解放する最も適切な方法について興味があります。

18
w m

free()が返す同じポインタをmalloc()に渡せば問題ありません。

例えば

char *readInput(size_t size)
 {
    char *input;
    int   chr;
    input = malloc(size + 1);
    if (input == NULL)
        return NULL;
    while ((i < size) && ((chr = getchar()) != '\n') && (chr != EOF))
        input[i++] = chr;
    input[size] = '\0'; /* nul terminate the array, so it can be a string */
    return input;
 }

 int main(void)
  {
     char *input;
     input = readInput(100);
     if (input == NULL)
         return -1;
     printf("input: %s\n", input);
     /* now you can free it */
     free(input);
     return 0;
  }

してはいけないことは

free(input + n);

input + nmalloc()が返すポインタではないためです。

しかし、あなたのコードには、あなたが注意すべき他の問題があります

  1. MAX_SIZEポインタを割り当てるsizeof(char)ではなく1であるsizeof(char *)を乗算する必要があるMAX_SIZEcharsにスペースを割り当てているので、代わりにMAX_SIZEを関数パラメータにすることもできます。固定バッファを割り当てる場合は、main()MAX_SIZEのようなサイズchar input[MAX_SIZE]で配列を定義し、それをreadInput()にパラメータとして渡して、malloc()およびfree()

  2. その量のスペースを割り当てていますが、whileループのオーバーフローを防止していません。i < MAX_SIZEを確認する必要があります。

17
Iharob Al Asimi

戻り型がchar*の関数を記述し、inputを返し、データの処理が完了したらfreeを呼び出すようユーザーに要求できます。

また、適切なサイズのバッファ自体をバッファサイズの制限と一緒に渡して、バッファに書き込まれた文字数を返すようにユーザーに要求することもできます。

4
orlp

これは古典的なcケースです。関数はその結果のためにメモリをmallocします。呼び出し側は戻り値を解放する必要があります。あなたは今、cメモリリークの薄い氷の上を歩いています。 2つの理由

最初 ;強制可能な方法で無料の要件を伝える方法はありません(つまり、コンパイラーまたはランタイムはあなたを助けることができません-引数の型が何であるかを指定することとは対照的です)。あなたはそれをどこかに文書化し、発信者があなたのドキュメントを読んでくれることを望んでいるだけです

2番目:呼び出し元が結果を解放することを知っていても、間違いを犯したとしても、メモリを解放しないエラーパスがいくつか発生します。これは即時のエラーを引き起こさず、問題はないように見えますが、3週間実行した後、メモリ不足でアプリがクラッシュします

これが、非常に多くの「現代の」言語がこのトピック、C++スマートポインター、Java、C#などのガベージコレクションに焦点を当てている理由です...

2
pm100