C ++ char array []メモリリーク[重複]

Aug 18 2020

char arr []を作成し、それに文字列リテラルを割り当てました

char arr[] = "some string";                  // arr occupies 12 chars in memory
std::cout << std::strlen(arr)  << std::endl; // lenght is 11 chars + 1 null-terminator
                                             //arr[11] is '\0'

次に、ヌルターミネータを6要素に入れます

arr[5] = '\0';
std::cout << std::strlen(arr) << std::endl; // lenght is 5 chars  + 1 null-terminator
  1. メモリリークですか?
  2. コンパイラは、最初の「\ 0」の後にメモリを解放する必要があることをどのように認識しますか?(いつ変数arrを削除しますか)
  3. このarr変数の長さを変更し、変数を削除するときに解放する必要がある量をコンパイラーに通知することは可能ですか?

回答

5 user253751 Aug 18 2020 at 13:03
  1. メモリリークですか?

番号。

  1. コンパイラは、最初の「\ 0」の後にメモリを解放する必要があることをどのように認識しますか?(いつ変数arrを削除しますか)

変数は12文字です。それは書くことと同じです:

char arr[12] = "some string";

したがって、常に12文字が解放されます。変数12文字の配列です。6番目の文字がたまたま「\ 0」であるという事実はまったく関係ありません。

ちなみに、6番目の文字を「\ 0」に設定すると、12文字の配列であるため、12文字すべてを使用できます。'\ 0'の後のものも。ただし、13文字を格納することはできません。

  1. このarr変数の長さを変更し、変数を削除するときに解放する必要がある量をコンパイラーに通知することは可能ですか?

いいえ。変数のサイズを変更することはできません。

6 cigien Aug 18 2020 at 13:03

このコードでは:

char arr[] = "some string";

変数arrは固定サイズの静的配列です。ここには動的なメモリ割り当てがないため、メモリリークについて心配する必要はありません。に何を書き込んだかに関係なく、コンパイラがメモリを処理しますarr

2 JoopEggen Aug 18 2020 at 13:07

完全を期すために。

次のように、割り当てられたメモリにもメモリリークはありません。

char* arr = (char*) malloc(12);
strcpy(arr, "some string");
arr[6] = '\0';
free(arr);

メモリ管理は、基礎となる使用法(nul-terended char *)ではなく、割り当てられたメモリ(12)によって行われます。(Cスタイル、C ++も同様)

1 Slava Aug 18 2020 at 13:56

後戻りしたようです。C ++の配列サイズは変更できません。その事実と、配列をポインタとして渡すと、その配列合意の実際のサイズの情報が失われるという事実のために、Cスタイルの文字列に対して作成されました-0バイト\0別名nullターミネータは文字列の動的な終わりとして扱われます。合意とは、Cスタイルの文字列を処理する関数がそれを文字列の終了として扱うことを意味します。これにより、異なる長さの文字列に固定サイズの配列を使用し、実際のメモリのサイズなしで1つのポインタのみを、そこから読み取る関数(たとえば、画面に出力)に渡すことができます。データを書き込む関数にchar配列を渡すときは、実際の配列サイズを指定する必要があることがよくあります。これにより、関数はnullターミネータがすでに存在する場合、それらの関数がnullターミネータを無視するため、範囲外のメモリにアクセスしません。

それだけです。この合意は、アレイが管理するさまざまなレイヤーで発生します。したがって、その配列に入力したデータが言語の観点からそのサイズに影響を与えることはありません。C++コンパイラの場合、固定サイズの配列を作成し、その配列にデータを入力します。存続期間が終了すると、コンパイラはそれを固定サイズの配列全体として破棄します。そこにゼロバイトを入れても入れなくてもかまいません。

VladfromMoscow Aug 18 2020 at 13:16

メモリリークは、メモリがプログラマによって演算子newを使用して割り当てられ、演算子deleteまたはを使用して削除されなかった場合に発生しdelete []ます。

この宣言では

char arr[] = "some string"; 

自動ストレージ期間または静的ストレージ期間のいずれかを持つのは、文字配列arrに割り当てられたコンパイラ(またはシステム)のメモリです。したがって、コンパイラ(またはシステム)は、割り当てられたメモリを解放する責任があります。割り当てられたメモリのアドレスは、コンパイラ(またはシステム)に認識されています。

このステートメントの使用

arr[5] = '\0';

アレイを再割り当てしませんでした。その内容をより正確に変更したのは、1バイトだけです。

コンパイラは、最初の「\ 0」の後にメモリを解放する必要があることをどのように認識しますか?(いつ変数arrを削除しますか)

コンパイラ(またはシステム)は、配列型のオブジェクトがどのように宣言されたかを知っているからです。

オブジェクトには12バイトが割り当てられました。

char arr[] = "some string"; 

このarr変数の長さを変更し、変数を削除するときに解放する必要がある量をコンパイラーに通知することは可能ですか?

オブジェクトのサイズを意味すると思います。いいえ、オブジェクトにメモリを割り当てたのはあなたではないため、オブジェクトのサイズを変更することはできません。

newたとえば、演算子を使用してオブジェクトを割り当てると、オブジェクトを再割り当てできます。

char *arr = new char[12];

std::strcpy( arr, "some string" );

//...

char *tmp = new char[20];

strcpy( tmp, "another " );
strcat( tmp, arr );

delete [] arr;
arr = tmp;