【C++】外伝編3_ダイナミックメモリ申請の結果
7891 ワード
ダイナミックメモリの結果
質問:ダイナミックメモリの申請は必ず成功しますか?一般的なダイナミックメモリ割り当てコード Cコード:
C++コード:知っておくべき事実 malloc関数申請に失敗した場合NULL値 を返す newキーワード申請に失敗した場合(コンパイラによって異なります) NULL値(古代) を返します. std::bad_alloc異常(現代)
質問:new文の異常はどのように投げ出されたのでしょうか. newキーワードのC++仕様における標準動作 スタックスペースで十分なメモリを申請 成功: 取得空間でコンストラクタ作成オブジェクト を呼び出す.は、オブジェクトのアドレス を返す.
失敗 std::bad_alloc異常
newキーワードのC++仕様における標準動作 newメモリ割り当て時 スペースが不足している場合は、グローバルなnew_が呼び出されます.handler()関数 new_handler()関数からstd::bad_alloc異常 はnew_をカスタマイズできますhandler()関数 デフォルトのnewメモリ割り当ての処理に失敗した場合
new_handler()では、メモリの整理を手動で行うことができ、より多くのスタックスペースを使用することができます. new_handler()関数の置換 は、戻り値なしパラメータなしの関数 をカスタマイズする.呼び出しset_new_handler()カスタム関数の設定 パラメータタイプvoid(*)() 戻り値がデフォルトのnew_handler()関数エントリアドレス
new_handler()の定義と使用
プログラミング実験:new_handlerプローブ
共通の実験コード:
実験1:異なるコンパイラにおけるnew_handler()動作
実験2:異なるコンパイラnew失敗挙動
質問:コンパイラにまたがってnewの動作を統一し、コードの移植性を高めるにはどうすればいいのでしょうか.ソリューション【動的メモリ割り当てに失敗した場合、空のポインタを返す】 グローバルレンジ(推奨しない) new/deleteの実装を再定義し、異常 を投げ出さないカスタムnew_handler()関数、異常 を投げ出さない
クラス階層範囲 new/deleteを再ロードし、異常 を投げ出さない
このダイナミックメモリ割り当て nothrowパラメータを使用して、newが異常 を放出しないことを示す.
プログラミング実験:ダイナミックメモリ申請
実験1:クラス階層範囲
実験2:単一ダイナミックメモリ割り当て範囲実験結論 すべてのコンパイラがC++の標準仕様 に従うわけではありません.コンパイラはnewのインプリメンテーションを再定義し、インプリメンテーションからbad_を放出することができる.alloc異常 コンパイラのデフォルト実装では、グローバルなnew_が設定されていない可能性があります.handler()関数 移植性の要求が高いコードについてはnewの具体的な詳細 を考慮する必要がある.
小結異なるコンパイラの動的メモリ割り当てにおける実装の詳細は 異なる. malloc関数は、メモリ申請に失敗したときにNULL値 を返す. newキーワードメモリ申請に失敗した場合 は、NULL値 を返すことができる bad_を投げ出す可能性がありますalloc異常
newに関する小さな知識点補足:指定したメモリ領域にオブジェクトを作成する(構造関数を手動で呼び出す必要がある)
以上の内容はディテソフトウェア学院シリーズの課程を参考にして、オリジナルを保護してください!
質問:ダイナミックメモリの申請は必ず成功しますか?
void code()
{
int* p = (int*)malloc(10 * sizeof(int));
if( p != NULL )
{
// ...
}
free(p);
}
C++コード:
void code()
{
int* p = new int[10];
if( p != NULL )
{
// ...
}
delete p;
}
質問:new文の異常はどのように投げ出されたのでしょうか.
new_handler()では、メモリの整理を手動で行うことができ、より多くのスタックスペースを使用することができます.
void my_new_handler()
{
cout << "No enough memory" << endl;
}
int main(int argc, char* argv[])
{
set_new_handler(my_new_handler);
// ...
return 0;
}
プログラミング実験:new_handlerプローブ
共通の実験コード:
#include
#include
#include
#include
using namespace std;
class Test
{
private:
int m_value;
public:
Test()
{
cout << "Test()" << endl;
m_value = 0;
}
~Test()
{
cout << "~Test()" << endl;
}
void* operator new (unsigned int size)
{
cout << "operator new: " << size << endl;
// return malloc(size);
return NULL; // !
}
void operator delete(void* p)
{
cout << "operator delete: " << p << endl;
free(p);
}
void* operator new[] (unsigned int size)
{
cout << "operator new[]: " << size << endl;
// return malloc(size);
return NULL; // !
}
void operator delete[](void* p)
{
cout << "operator delete[]: " << p << endl;
free(p);
}
};
実験1:異なるコンパイラにおけるnew_handler()動作
void my_new_handler()
{
cout << "void my_new_handler()" << endl;
}
void ex_func_1()
{
new_handler func = set_new_handler(my_new_handler); // !
try
{
cout << "func = " << func << endl;
if( func )
{
func();
}
}
catch(const bad_alloc&)
{
cout << "catch(catch bad_alloc&)" << endl;
}
}
int main()
{
ex_func_1();
return 0;
}
:[g++]
func = 0
:[vc++2010]
func = 00000000
:[bcc]
func = 0x00401474
catch(catch bad_alloc&)
:
,g++,vc++2010 new_handler() ;
gcc new_handler() , bad_alloc 。
実験2:異なるコンパイラnew失敗挙動
void ex_func_2()
{
Test* pt = new Test();
cout << "pt = " << pt << endl;
delete pt;
pt = new Test[5];
cout << "pt = " << pt << endl;
delete[] pt;
}
int main()
{
ex_func_2();
return 0;
}
:[g++]
Test()
:[vc++2010]
operator new: 4
pt = 00000000
operator new[]: 24
pt = 00000000
:[bcc]
operator new: 4
pt = 00000000
operator new[]: 24
pt = 00000000
:
g++ :
new NULL, 0 , 。 ,m_value = 0, 。
vc++2010:
new NULL, ,
bcc:
new NULL, ,
質問:コンパイラにまたがってnewの動作を統一し、コードの移植性を高めるにはどうすればいいのでしょうか.
プログラミング実験:ダイナミックメモリ申請
実験1:クラス階層範囲
#include
#include
#include
#include
using namespace std;
class Test
{
private:
int m_value;
public:
Test()
{
cout << "Test()" << endl;
m_value = 0;
}
~Test()
{
cout << "~Test()" << endl;
}
void* operator new (unsigned int size) throw() // !
{
cout << "operator new: " << size << endl;
// return malloc(size);
return NULL; // !
}
void operator delete(void* p)
{
cout << "operator delete: " << p << endl;
free(p);
}
void* operator new[] (unsigned int size) throw() // !
{
cout << "operator new[]: " << size << endl;
// return malloc(size);
return NULL; // !
}
void operator delete[](void* p)
{
cout << "operator delete[]: " << p << endl;
free(p);
}
};
void ex_func_2()
{
Test* pt = new Test();
cout << "pt = " << pt << endl;
delete pt;
pt = new Test[5];
cout << "pt = " << pt << endl;
delete[] pt;
}
int main()
{
ex_func_2();
return 0;
}
:[g++]
operator new: 4
pt = 0
operator new[]: 24
pt = 0
:[vc++2010]
operator new: 4
pt = 00000000
operator new[]: 24
pt = 00000000
:[bcc]
operator new: 4
pt = 00000000
operator new[]: 24
pt = 00000000
実験2:単一ダイナミックメモリ割り当て範囲
#include
#include
#include
#include
using namespace std;
void ex_func_3()
{
int* p = new(nothrow) int[10]; // !
cout << "p = " << p << endl;
delete p;
}
int main()
{
ex_func_3();
return 0;
}
:
p = 0x8300008
小結
newに関する小さな知識点補足:指定したメモリ領域にオブジェクトを作成する(構造関数を手動で呼び出す必要がある)
#include
using namespace std;
int main()
{
int bb[2] = {0};
struct ST
{
int x;
int y;
};
ST* pt = new(bb) ST(); // !
pt->x = 1;
pt->y = 2;
cout << bb[0] << endl;
cout << bb[1] << endl;
pt->~ST(); //
return 0;
}
:
1
2
以上の内容はディテソフトウェア学院シリーズの課程を参考にして、オリジナルを保護してください!