C / C ++メモリ管理-C / C ++メモリ分散の実現原理、新規および削除
1. C / C ++メモリ分散
05-C言語の高度な動的メモリ管理このブログでは、動的メモリ管理とC言語でのメモリリークの事例を詳細に紹介しています
。Linuxの概念-プロセスアドレス空間このブログでは、プロセスアドレス空間を紹介します。
C / C ++の場合、メモリ分布を次の図に示します。
C / C ++では、アドレス空間はカーネル空間、スタック、メモリマッピング領域、ヒープ、データセグメント、およびコードセグメントに分割されます。次の点に注意する必要があります。
- スタックは、スタック、非静的ローカル変数/関数パラメーター/戻り値などとも呼ばれます。スタックは下に向かって大きくなります。
- メモリマップセグメントは、共有動的メモリライブラリをロードするための効率的なI / Oマッピング方法です。ユーザーは、システムインターフェイスを使用して、プロセス間通信用の共有共有メモリを作成できます。
- ヒープは、プログラムの実行中に動的メモリ割り当てに使用され、ヒープが大きくなる可能性があります。
- データセグメント-グローバルデータと静的データを格納します。
- コードセグメント-実行可能コード/読み取り専用定数。
2、C / C ++メモリ管理モード
2.1 C言語での動的メモリ管理方法(malloc / calloc / reallocおよびfree)
05-C言語の高度な動的メモリ管理このブログでは、C言語の動的メモリ管理について詳しく紹介していますが、この記事では繰り返し説明しません。
Q1:malloc / calloc / reallocの違いは何ですか?
- Mallocは、メモリから継続的に使用可能なスペースを申請します。
- callocとmallocの違いは、適用される各スペースが0に初期化されることです。
- 元のメモリ空間のサイズの調整に基づいて、realloc関数は元のメモリ内のデータを新しい空間に移動します。
reallocがメモリスペースを調整する場合、2つの状況があります。
- 状況1:元のスペースの後に十分なスペースがあります。ケース1の場合、メモリを拡張する場合は、元のメモリの直後にスペースを追加すると、元のスペースのデータは変更されません。
- 状況2:元のスペースの後に十分なスペースがありません。拡張方法:使用するヒープスペース上で、適切なサイズの別の連続したスペースを見つけます。この関数は、新しいメモリアドレスを返します。
2.2 C ++メモリ管理方法
言語メモリ管理方法はC ++でも引き続き使用できますが、使用するのが無力で面倒な場合があるため、C ++は独自のメモリ管理方法を提案しました。new演算子とdelete演算子による動的メモリ管理です。
<1>新規/削除操作組み込み型
//2.2.1
void Test3()
{
//动态申请一个int类型的空间
int* ptr4 = new int;
//动态申请一个int类型的空间并初始化为10
int* ptr5 = new int(10);
//动态申请10个int类型的空间
int* ptr6 = new int[10];
delete ptr4;
delete ptr5;
delete[] ptr6;
}
注:
単一要素のスペースを申請して解放するには、new演算子とdelete演算子を使用してペアで表示します。連続スペースを申請して解放するには、new []とdelete []を使用してペアで表示します。
<2>新規/削除操作カスタムタイプ
Dateクラスが次のようになっていると仮定します
//2.2.2
class Date
{
private:
int _year;
int _month;
int _day;
public:
Date(int year = 1900, int month = 1, int day = 1)
:_year(year)
, _month(month)
, _day(day)
{
cout << "Date(int yaer = 1900, int month = 1, int day = 1)"<<endl;
}
~Date()
{
cout << "~Date()" << endl;
}
};
新しいmallocを使用してスペースを申請し、解放して削除してスペースを解放します
void Test4()
{
//申请单个Date类型的空间
Date* d1 = (Date *)malloc(sizeof(Date));
//申请10个Date类型的空间
Date* d2 = (Date *)malloc(sizeof(Date) * 10);
free(d1);
free(d2);
cout << "--------------" << endl;
//申请单个Date类型的空间
Date* d3 = new Date;
//申请10个Date类型的空间
Date* d4 = new Date[10];
delete d3;
delete[] d4;
}
注意
- カスタムタイプのスペースを適用する場合、newはコンストラクタを呼び出し、deleteはデストラクタを呼び出しますが、mallocとfreeは呼び出しません。
- newを使用して
new Date
とを定義しますnew Date()
が、日付型定義変数の場合は、はい。Date d1
ただしDate d1()
、システムによって関数宣言として認識されるため、そうではありません。
2.3演算子の新規および演算子の削除機能(強調)
- newとdeleteは、ユーザーが動的メモリを適用および解放するための演算子です。operatornewとoperator deleteは、システムによって提供されるグローバル関数です。
- Newは、下部にある演算子newグローバル関数を呼び出してスペースを適用し、deleteは下部にある演算子deleteグローバル関数を使用してスペースを解放します。
これらの2つのグローバルな認識機能を実装することにより、オペレーターnewは、mallocスペースアプリケーションが正常にリターンを指示した場合、またはユーザーがメジャーを提供した場合にユーザーが提供した応答メジャースペースの実装が不足している場合、実際にはmallocによって空の部屋を申請します。引き続き適用するか、例外をスローします。演算子deleteは、最終的にfreeを介してスペースを解放します。
3つ目は、newとdeleteの実現原理です。
3.1ビルトインタイプ
要求された組み込みタイプのスペース、newとmalloc、deleteとfreeが基本的に類似している場合、違いは次のとおりです。
- 新規/削除は、単一の要素のスペースに適用され、解放されます。
- new [] / delete []は、連続スペースを適用して解放します。
- Newは、アプリケーションが失敗すると例外をスローし、mallocはアプリケーションが失敗するとNULLを返します。
3.2カスタムタイプ
<1> new / new []およびdelete / delete []の原則
第四に、malloc / freeとnew / deleteの違い
malloc / freeとnew / deleteに
共通するものは次のとおりです。
それらはすべてヒープからスペースを申請し、ユーザーが手動で解放する必要があります。
違いは次のとおりです。
- mallocとfreeは関数、newとdeleteは演算子です
- mallocによって要求されたスペースは初期化されません。新しいものは初期化できます。
- mallocがスペースに適用される場合、スペースのサイズを手動で計算して渡す必要があります。新規の後にスペースのタイプを入力するだけで済みます。
- mallocの戻り値はvoid *であり、使用時に強制する必要があります。newの後にスペースのタイプが続くため、newは必要ありません。
- mallocがスペースの適用に失敗すると、NULLを返すため、使用する場合はnullである必要があります。newは必要ありませんが、newは例外をキャッチする必要があります。
- カスタムタイプのオブジェクトを申請する場合、malloc / freeはスペースを開くだけで、コンストラクタと>デストラクタを呼び出しません。Newは、スペースを申請した後にコンストラクタを呼び出してオブジェクトの初期化を完了し、deleteはスペースを呼び出します。スペースを解放する前のデストラクタ。この関数は、スペース内のリソースのクリーンアップを完了します。
5、メモリリーク
5.1メモリリークとは何ですか?メモリリークの害は何ですか?
メモリリーク:メモリリークとは、プログラムが過失またはエラーのために使用されなくなったメモリを解放できない状況を指します。メモリリークは、メモリの物理的な消失を意味するものではありませんが、アプリケーションがメモリの特定のセグメントを割り当てた後、設計エラーのために、メモリのこのセグメントの制御を失い、メモリの浪費を引き起こします。
害:オペレーティングシステムやバックグラウンドサービスなど、実行時間の長いプログラムでメモリリークが発生すると、メモリリークが発生し、応答がますます遅くなり、最終的にはフリーズします。
5.2メモリリークの分類
ヒープリーク:
ヒープメモリとは、プログラム実行のニーズに応じて、ヒープからmalloc / calloc / realloc / newを介して割り当てられるメモリのことであり、使用後に対応するfreeまたはdeleteを呼び出して削除する必要があります。プログラムの設計エラーによりメモリのこの部分が解放されないと仮定すると、スペースのこの部分は将来使用されなくなり、ヒープリークが生成されます。
システムリソースの漏洩:
システムによって割り当てられたリソースを使用するプログラムを指します。たとえば、ソケット、ファイル記述子、パイプなどは、対応する関数を使用して解放されないため、システムリソースが浪費され、システムパフォーマンスが大幅に低下し、システムの実行が不安定になります。
5.3メモリリークを回避する方法
イベント前の防止-スマートポインタ、その後のエラーチェック-リーク検出ツール