を使用set_new_handler
し、ハンドラー関数が呼び出されerrno
た場合、設定されることが保証されmalloc
ます。それとも使ったほうがいいstrerror(ENOMEM)
ですか?errno
Microsoft C++ と GCC で動作しますが、それが保証されているかどうかという問題が残ります。
2 に答える
new
(またはmalloc
、さらに言えば) set という要件はありませんerrno
。両方ともstd::bad_alloc
、errno
. (実装の品質の観点から、私は を変更したくない、new
またはmalloc
変更を許可されませんerrno
。Posix 要件を無視しません。)
errno
動的メモリ割り当ての失敗を検出するには十分ではないと思います。N3337、特に3.7.4.1 割り当て関数を見る:
2 [...] 要求されたスペースのサイズがゼロであっても、要求は失敗する可能性があります。要求が成功した場合、値 p1 が後でオペレーター delete に渡されない限り、返される値は、以前に返された値 p1 とは異なる非 null ポインター値 (4.10) p0 になります。サイズ 0 の要求として返されたポインターを逆参照した場合の影響は未定義です。35
3ストレージの割り当てに失敗した割り当て関数は、現在インストールされている new-handler 関数 (18.6.2.3) を呼び出すことができます (存在する場合)。[ 注: プログラム提供の割り当て関数は、std::get_new_handler 関数 (18.6.2.4) を使用して、現在インストールされている new_handler のアドレスを取得できます。--end note ] 非スロー例外仕様 (15.4) で宣言された割り当て関数がストレージの割り当てに失敗した場合、null ポインターを返す必要があります。ストレージの割り当てに失敗したその他の割り当て関数は、型 std::bad_alloc (18.6.2.1) のハンドラー (15.3) に一致する型の例外をスローすることによってのみ、失敗を示すものとします。
および脚注 35 (これは単なる目安であり、規範的ではありません):
35) std::malloc() または std::calloc() を呼び出すことによって演算子 new() を実装できるようにすることを意図しているため、ルールは実質的に同じです。C++ は、null 以外のポインターを返すためにゼロ要求を必要とする点で C とは異なります。
ここで、C 標準ドラフト N1570 に進み、7.5 Errors<errno.h>
を見てください。
3初期スレッドの errno の値は、プログラムの起動時にゼロです (他のスレッドの errno の初期値は不定値です) が、ライブラリ関数によってゼロに設定されることはありません.202) errno の値は、エラーがあるかどうかに関係なく、ライブラリ関数呼び出しによる非ゼロ。 ただし、errno の使用がこの国際標準の関数の説明で文書化されていない場合。
障害errno
によって設定される可能性があるようですが、これは必須ではありません。malloc
また、N1570 からの7.22.3 メモリ管理機能が指定されていないか、malloc
またはフレンドが設定する必要がありますerrno
。
私の提案は、標準が保証するものに固執し、std::bad_alloc
によってスローされた例外 ( )を使用することですnew
(つまり、 no-throw を使用しないでnew
ください)。