c++メモリ漏洩(一):メモリ漏洩及びメモリ漏洩のよくある状況を理解する

1936 ワード


プログラムには通常、静的メモリとスタックメモリが含まれています.静的メモリは、ローカルstaticオブジェクト、クラスstaticデータメンバー、および任意の関数以外に定義された変数(グローバル変数)を保存するために使用されます.スタックメモリは、関数内に定義された非staticオブジェクトを保存するために使用されます.静的またはスタックメモリに割り当てられたオブジェクトは、コンパイラによって自動的に作成され、破棄されます.スタックオブジェクトの場合、定義されたブロックの実行時にのみ存在し、プログラムは終了し、スタックオブジェクトも破棄されます.staticオブジェクトとグローバルオブジェクトは、プログラムの終了時に破棄されます.静的メモリとスタックメモリのほかに、プログラムはスタックと呼ばれるメモリプールを持っています.スタックスペースを使用するには、ダイナミックメモリ割り当てが必要です.
 
メモリリーク:プログラム内で自分で動的に割り当てられたスタックメモリが何らかの原因でプログラムが解放されていないか、解放できないため、システムメモリの浪費を招き、プログラムの実行速度が遅くなり、システムがクラッシュするなどの深刻な結果をもたらす.
サーバプログラムや長時間実行する必要があるプログラムでは、メモリ漏洩の検出と解決がプログラマーに必須のスキルです.
 
1.メモリ漏れが発生した場合のまとめ
まずc++の構文上のエラー使用によるメモリ漏洩をまとめるので,プログラムを記述する際にはエラーの記述をできるだけ避ける.
(1)newとdelete演算子を正しく使用するには,newとdeleteが一致して使用されることが初心者にとって最もよく見られることに注意しなければならない.一般にエラーの箇所は以下の例のようにポインタpの値が別の関数で用いられる.
 
char * FunA()
{
	char *p = new char;
	return p;
}
void FunErrorB()
{
	char *b = FunA();
	//  delete p	
}

(2)オブジェクト配列を解放する場合delete[]は使用されません.例に示すように、
 
 
Void FunErrorA()
{
	Char *p = new char[10];
	Delete p;
}

 
 
 
(3)二重ポインタ解放エラーで,ポインタ解放の漏れがある.例のように二重ポインタを正しく解放する
Void FunRightA()
{
	Char **p = new char*[10];
	For(int i=0;i<10;i++)
	{
		p[i] = new char[10];
	}
	If(p!=nullptr)
	{
		For(int i=0;i<10;i++)
		{	Delete []p[i];
			p[i] = nullptr;
		}
		Delete []p;
		p = nullptr;
	}
}

 
(4)コピーコンストラクタが欠落している.クラスに存在するメンバー変数がポインタである場合、付与=演算と値によるパラメータ伝達を行う際には、コピーコンストラクタを再ロードし、ポインタコピーの部分を再実現する必要がある.
(5)基底クラスの構造関数を虚関数として定義していない.ベースクラスポインタがサブクラスオブジェクトを指す場合、ベースクラスの構造関数がvirtualでない場合、サブクラスの構造関数は呼び出されず、サブクラスのリソースが正しく解放されていないため、メモリが漏洩します.
 
 
(6)呼び出し在庫がメモリに漏れている.パーソナルパッケージまたは完全にテストされていないライブラリを使用する場合は、このライブラリが本プログラムにパフォーマンスに影響を及ぼさないことを確認します.
メモリ漏洩が発生した場合、メモリ漏洩が発生したことを確認し、メモリ漏洩の場所を特定するにはどうすればいいですか.
c++メモリ漏洩(二):性能モニタを用いてメモリ漏洩の確認を行う
c++メモリリーク(3):メモリリークの位置決めと解決