どうやら、Habréの例外の週が成功しました:)。 マイナスになることを恐れないように、カルマの十分な「枕」を蓄積したので、私は、おそらく、この問題についての私の意見も表明します。 C ++、Objective-C、C#、Java、Python、Rubyなどの商業開発での実際的な経験に基づいて、意見が純粋に個人的なものであるということを直ちに予約してください。
間違いは何ですか?
血まみれの混乱に着手する前に、戦場を評価し、用語を同期することをお勧めします。 ソフトウェア開発のコンテキストでの「エラー」の下では、まったく異なることを理解できるため、まずはこれらのエンティティを何らかの方法で説明し、呼び出してみます。
- プログラムで発生する可能性のある最も単純なことは、オペレーティングシステムまたはハードウェアの障害です。 動作しなかったCreateEvent()またはpthread_mutex_lock()システムコール、ゼロによる除算、システムコールの結果のガベージ-これらはすべて、障害のあるハードウェアからシステムのウイルスまで、通常は私たちとプログラムからのさまざまな理由で発生しますあまり依存していません。
- もう少し複雑な状況は、必要なリソースが不足していることです。 突然、メモリ、ハンドル、ファイル記述子が終了する場合があります。 必要なファイルを書き込んだり読み取ったりする権利がない場合があります。 パイプが開かない場合があります。 またはその逆-閉じないでください。 データベースへのアクセスは、そうでない場合があります。 このような状況は、プログラム(必要なメモリが多すぎる)とシステムの不安定性(ウイルスのメモリが多すぎる)によってすでに発生している可能性があります。
- そして、最も一般的な状況は、プログラムのロジックまたはその部分の相互作用の誤りです。 存在しないリストアイテムを削除し、無効な引数を使用してメソッドを呼び出し、非スレッド操作をマルチスレッドで実行しようとしています。 原則として、これはプログラムの不正な動作(「ツールバーが消えた」)につながるか、アクセス違反/未処理の例外でクラッシュします。
あなたが見ることができるように、多くの異なる悪いことが起こる可能性があります-しかし、これは完全なリストではありません:)。 プログラマは何をすべきですか? ここで、私の意見では、非常に興味深い重要な質問に直面しています-プログラムはこのエラーまたはそのエラーにどのように正確に応答しますか? おそらく今、私は純粋に個人的な意見を表明していることをもう一度思い出します。 そして、私は次のように言います-エラーに正確に応答する方法は、特定のプログラムに完全に依存します。 ドライバーのメモリが足りなくなった場合、ユーザーが死のブルースクリーンを受け取らないように、すべての犠牲を払って生き残る必要があります。 面白い農場のようなおもちゃでメモリが足りなくなった場合、落ちて謝罪し、バグレポートを開発者に送るように頼むのは理にかなっています。 再起動せずに数か月間スピンするように設計されたシステムサービスは、CreateEvent()エラーに共感する必要があります。 Photoshopなどのアプリケーションでの同じエラーは、システムがすぐに死ぬ可能性が高いことを意味します。エラーを飲み込もうとするよりも、正直にクラッシュする方がよいでしょう。 したがって、エラーを
予想されるエラーと
予期しないエラーに分けることができます。 異なるプログラムおよび異なる要件の場合、同じエラーが予想されるものと予期しないものの両方と見なされる可能性があります。 何らかの形で予想されるエラーを処理しています。 ファイルを開けませんでした-これについてユーザーに話し、作業を続けます。 ギガバイトのファイルをアップロードするためのメモリの割り当てに失敗しました-これについてユーザーに話し、作業を続けます。 ほとんどの場合、予期しないエラーは発生しません。 20バイトを割り当ててオブジェクトを作成しようとすると、メモリ不足になります。 プログラム全体に3つの部分があるシステムオブジェクトは作成しませんでした。 仕様に従って読み取る必要のあるシステムパイプは読み取れませんか? プログラムを不安定な状態のままにしてから、ユーザーのデータを台無しにするよりも落ちるほうがよいでしょう。 彼がプログラムを再起動する場合、彼は彼の日の終わりまで破損したファイルのためにそれを嫌います。 深刻な場合には、自動保存機能があり、ウォッチドッグがあれば再起動します。
例外の前に何が起こったのですか?
手続き型プログラミングの全盛期では、エラーを処理するための構文は簡単で、関数が返すものに基づいていました。 関数がTRUEを返した場合-すべては正常ですが、FALSEの場合はエラーが発生しました。 同時に、エラーを処理するための2つのアプローチがすぐに目立ちました。
- ツーインワンアプローチ-関数は、予期されるエラーと予期しないエラーの両方に対してFALSEまたはNULLポインターを返します。 通常、このアプローチは、ほとんどのエラーが安全に致命的でクラッシュしたとみなされる汎用APIおよびユーザープログラムコードに適用されました。 共有が必要なまれなケースでは、GetLastError()という形式の追加の機械が使用されました。 そのときのコードスニペット。あるファイルから別のファイルにデータをコピーし、問題が発生した場合にエラーを返します。
BOOL Copy( CHAR* sname, CHAR* dname )
{
FILE *sfile = 0, *dfile = 0;
void* mem = 0;
UINT32 size = 0, written = 0;
BOOL ret = FALSE;
sfile = fopen( sname, "rb" );
if( ! sfile ) goto cleanup;
dfile = fopen( dname, "wb" );
if( ! dfile ) goto cleanup;
mem = malloc( F_CHUNK_SIZE );
if( ! mem ) goto cleanup;
do
{
size = fread( sfile, mem, F_CHUNK_SIZE );
written = fwrite( dfile, mem, size );
if( size != written ) goto cleanup;
}
while( size )
ret = TRUE;
cleanup:
if( sfile) fclose( sfile );
if( dfile) fclose( dfile );
if( mem ) free( mem );
return ret;
}
- , FALSE , ( error), . , apache, ( ) ( , 20 ). , ( FALSE) ( HANDLE).
BOOL Copy( CHAR* sname, CHAR* dname, OUT HANDLE* error )
{
HANDLE sfile = 0, dfile = 0, data = 0;
UINT32 size = 0;
ENSURE( PoolAlloc() );
ENSURE( FileOpen( sname, OUT& sfile, OUT error ) );
REQUIRE( SUCCESS( error ) );
ENSURE( FileOpen( dname, OUT& dfile, OUT error ) );
REQUIRE( SUCCESS( error ) );
ENSURE( MemAlloc( OUT& data ) );
REQUIRE( SUCCESS( error ) );
do
{
ENSURE( FileRead( sfile, F_CHUNK_SIZE, OUT& data, OUT error ) );
REQUIRE( SUCCESS( error ) );
ENSURE( FileWrite( dfile, & data ) );
REQUIRE( SUCCESS( error ) );
ENSURE( MemGetSize( OUT& size ) )
}
while( size );
ENSURE( PoolFree() );
return TRUE;
}
, , — .
, . (fopen, fclose) . (BOOL ret , ENSURE ) .
— . — , , . — if REQUIRE — . , :
- — — .
void Copy( string sname, string dname )
{
file source( sname );
file destination( sname );
source.open( "rb" );
destination.open( "wb" );
data bytes;
do
{
bytes = source.read( F_CHUNK_SIZE );
destination.write( bytes )
}
while( bytes.size() )
}
- — / nullable :
bool Copy( string sname, string dname )
{
file source( sname );
file destination( sname );
if( ! source.open( "rb" ) || ! destination.open( "wb" ) ) return false;
data bytes;
do
{
bytes = source.read( F_CHUNK_SIZE );
if( bytes.isValid() )
{
if( ! destination.write( bytes ) ) return false;
}
}
while( bytes.isValid() && bytes.size() )
}
?
, :). , . . . — . — - ? :
- , C++, . , . , .
- API . (checked) (unchecked), API , .
- « ». , , try catch , .
. , , — C++. « », « » « » C++. , API , . , — API , .