C ++新規、削除、動的メモリ

動的メモリ=スマートポインタ+直接管理(新しい削除)

動的メモリを使用する理由

  1. プログラムは、使用する必要があるオブジェクトの数がわかりません
  2. 必要なオブジェクトのタイプがわかりません
  3. 複数のオブジェクト間でデータを共有する必要がある

C ++メモリ分類:スタック領域、ヒープ領域、グローバル領域(静的領域)、定数領域、コード領域
静的スタック、ローカル変数
動的ヒープ、新しいmalloc

1. c ++の4つのスマートポインター:(ヘッダーメモリ)

auto_ptrは廃止され、unique_ptrに置き換えられました!
shared_ptrを使用すると、複数のポインターが同じオブジェクトを指すことができます。2つのオブジェクトは、
shared_ptrメンバー変数を使用して互いにポイントするため、循環参照が発生し、参照カウントが無効になり、メモリリークが発生します。共有所有権の概念を実装します。複数のスマートポインタが同じオブジェクトを指すことができます。オブジェクトとその関連リソースは、「最後の参照が破棄された」ときに
make_shared関数を解放します。これは、動的メモリを割り当てて使用する最も安全な方法です。

make_shared在动态内存中分配一个对象并初始化,返回指向该对象的shared_ptr。
shared_ptr<int> p=make_shared<int>(0)//指向值为0的int的shared_ptr
auto q(p);//用p来初始化q,两个指向相同对象。。引用计数加一!!!
q.use_count()//计数
auto r=make_shared<int>(43);
r=s;//r原来指向的对象没有引用者,会调用析构函数,销毁对象。释放内存!!!
shared_ptr<int> p1(new int(1024));//shared_ptr用new初始化
p1.reset//释放

unique_ptrrは、それが参照するオブジェクトを「unique」が所有し、同時に1つのunique_ptrのみが指定されたオブジェクトを指すことができます(他のポインターがこのオブジェクトを指す必要があります、最初のリリース!!!)。リソースリークを回避する

unique_ptr<int> u1 (new int(1024));//不支持拷贝和赋值
u1=nullptr;//释放u指向的对象,将u置空
u1.reset();//释放u指向的对象
u1.release();//u放弃原指针的控制权,将u置空。返回指针,返回指针,返回指针!!!!
unique_ptr<int> p2(p1.release());//将所有权从p1转移给p2

weak_ptrは、循環参照によって引き起こされるメモリリークを解決します。shared_ptrによって管理されるオブジェクトを指しますが、use_count()は増やしません。

auto p=make_shared<int>(42);
weak_ptr<int>wq(p);//wq弱共享p。


スマートポインターの役割:スマートポインターの役割は、ポインターを管理することです。適用されたスペースは、関数の最後に解放されるのを忘れ、メモリリークが発生します。スマートポインターの使用を回避できます。スマートポインタはクラスです。クラスのスコープを超えると、クラスは自動的にデストラクタを呼び出してリソースを解放します。

2、新しい、新しい[]およびmalloc

違い:
新しい[]の配列要素の基本型は、削除と削除[]の両方で解放できます。
新しい[]の配列要素がカスタム型の場合、配列は削除[]でのみ解放できます。スペース。
配列のYuan Shuがカスタムタイプの場合、deleteはスペースを解放するときに配列の最初の要素のデストラクタのみを呼び出し、
delete []はスペースを解放するときに配列のすべての要素のデストラクタを呼び出します。
new / delete malloc / free
キーワードは、ライブラリ関数をオーバーロードする可能性があります。
コンストラクタ/デストラクタを呼び出します。オブジェクト+メモリメモリ
はオブジェクトへのポインタを返し、オブジェクトはvoid *を返します
。また、データタイプに応じてメモリ自動的に割り当てるように強制する必要があります。アプリケーション中に指定されたサイズは、再割り当ておよび拡張できます。
割り当てが失敗した場合は、bad_mallocを返します。キャッチを試みます。割り当てが失敗した場合は、NULLを返します。malloc
とnew 違い:
1. new / deleteはC ++キーワードであり、コンパイラのサポートが必要です。Newはコンストラクタを呼び出します。メモリサイズを指定することはできず、返されるポインタを強制する必要はありません。内部データ型に加えて、動的オブジェクトもサポートされています。オブジェクト+メモリ、オブジェクトへのポインタを返します。newが失敗した場合、badallloc例外が返されます。Nothrowは例外をスローしません。2。mallocは
アプリケーションメモリのサイズを指定する必要があり、返されるポインタは強制される必要があります。malloc / freeはライブラリ関数であり、ヘッダーファイルのサポートが必要です。内部データ型のみがサポートされています。メモリ。void *を返す

int *arr=int*malloc(sizeof(int)*n)
free(arr);
//如果new失败,返回一个bad_alloc类型的异常
int *pi=new int(1024);//pi指向对象的值为1024
string *ps=new string//string初始化为空了
auto p1=new auto(obj);//obj是int,那么p1就是int*了
const int *p=new const int(1024);
delete p;//销毁对象 释放内存。所以p必须是对象或空指针
动态数组(不建议用,还是建议用标准容器)
int *p=new int[40];//表示有40个int
int *p1=new int[40]()//初始化为0了
delete []p;//逆序先销毁最后一个,,,直到第一个元素
智能指针unique_ptr可以管理动态数组new[]
unique_ptr<int[]> p(new int[10]);
p.release();//自动调用delete[]
allocator类
allocator<string>alloc;
auto const p=alloc.allocate(n);//分配n个未初始化的string
alloc.deallocate(p,n)//释放p指向的那块内存
alloc.desdoy(p);//调用析构函数,销毁p指向的对象

auto q=p;//q指向最后一个元素位置
alloc.construct(q++,"hello");//初始化构造的对象
while(q!=p)
    alloc.destroy(--q);//销毁对象(必须是先构造的元素)

3. mallocの原理。brkおよびmmapシステムコール?

メモリの断片化とシステムコールのオーバーヘッドを削減するために、mallocはメモリプール方式を使用し、最初に大きなメモリブロックをヒープ領域として適用し、次にヒープを複数のメモリブロックに分割します(ブロックはメモリ管理の基本単位です)。 、適切な空きブロックをヒープ領域から直接割り当てます。mallocは、ヒープを連続した異なるサイズのブロック(割り当てられたブロックと空きブロック)に分割し、空きブロックを二重にリンクされたリストに接続します。
ユーザーがメモリを申請すると、mallocはすべての空きブロックを容易にし、適切なサイズのブロックを割り当てます。(メモリをマージするとき、mallocは境界表記を使用し、各ブロックの前後のブロックが割り当てられているかどうかに基づいてマージするかどうかを決定します。)
Mallocは通常、メモリを適用するときにbrkまたはmmapシステムコールを使用します。アプリケーションメモリが128k未満の場合、システム関数brkを使用してヒープ領域に割り当てます。128kより大きい場合は、mmapを使用してマッピング領域に割り当てます。

4.ワイルドポインターとダングリングポインター

ぶら下がりポインタはそのようなポインタです。以前は有効なアドレスを指していましたが、現在は有効なアドレスを指していません(実際には、このポインタ領域から元のアドレスにアクセスすることはできません)。これは通常、ポインタが指すメモリユニットが解放され、有効ではなくなったためです。このポインターが指すアドレス空間にアクセスしようとしない限り、ぶら下がりポインターに問題はありません。ぶら下がりポインタを残さないことが常にベストプラクティスです。

#include <stdlib.h>
void func(){
    char *dp = (char *)malloc(A_CONST);
    free(dp);         //dp变成一个空悬指针
    dp = nullptr;        //dp不再是空悬指针
}

上の例は、動的に適用されたメモリを解放するだけでなく、freeまたはdeleteが呼び出されたときに、関連するポインターもNULLを指す必要があることを思い出させます。

ワイルドポインターは、正しく初期化されていないポインターであり、ランダムなメモリアドレスを指します。ワイルドポインターの存在は重大な誤りです。

ワイルドポインター:ランダムポインターはランダムなメモリ空間を指し、プログラムによって制御されません。
初期化されていない場合、またはアクセス権のないメモリ空間を指している場合、後で逆参照すると問題が発生します。

ワイルドポインター
1の原因ポインター変数が初期化されていません。ポインタ変数が最初に作成されるとき、それは自動的にNULLポインタにはならず、そのデフォルト値はランダムであり、イライラします。
2.ポインターpが解放または削除された後、それはNULLに設定されないため、人々は誤ってpが正当なポインターであると信じさせます。//これは空のぶら下がりポインタです
3.ポインタ操作が変数のスコープを超えています。この状況は予測できません。

5.メモリリーク

定義:メモリリークとは、過失またはエラーが原因で使用されなくなったメモリを解放できないプログラムを指します。
メモリオーバーフロー:使用されたメモリ領域がシステムの割り当てを超えています
結果:パフォーマンスの低下、メモリの枯渇
一般なタイプ:
ヒープメモリリーク:malloc、new、およびreallocが使用されます。役に立たない解放と削除の解放
システムリソースリーク:プログラムに割り当てられたリソースは、ビットマップ\ハンドル\ソケットなどの対応する関数を使用して解放されません。
基本クラスデストラクタが仮想関数でない場合、基本クラスはサブクラスオブジェクトを指すときに呼び出されませんサブクラスデストラクタ。メモリリークを引き起こします。
トラブルシューティング:BoundsChecker、ランタイム中に発生するさまざまなエラーを特定し
、プログラムのデバッグバージョンをデバッグして実行します。CRT(Cランタイムライブラリ)、ランタイム関数呼び出しスタック、メモリリーク時にプロンプ​​トされるメモリ割り当てシリアル番号(統合開発環境の出力)ウィンドウ)、メモリリークの原因の包括的な分析、メモリリークを排除します。
メモリリークを検出するためのLinuxツール-valgrind
ウィンドウは、CRTライブラリ関数を使用して
mtraceを検出し、mallocを追跡および検出します。または、メモリアプリケーションの統計関数を手動で追加して解放し、リークを特定するためにそれらが一貫しているかどうかを確認します

解決策:スマートポインターを使用すると、
メモリがnull メモリオーバーフローに初期化されます。これは、プログラムがメモリに適用すると、使用するのに十分なメモリスペースがなく、メモリ不足が表示されることを意味します。たとえば、整数が適用されますが、長い機能が格納されます。保存された数は、メモリオーバーフローです。

19件のオリジナル記事を公開しました Like9 訪問2900

おすすめ

転載: blog.csdn.net/u013031697/article/details/104824662