2009-07-31 24 views
2

Windows 2003サーバーにCOM +経由でネイティブC++アプリケーションを実行しています。私は最近、イベントビューアから例外をスローすること、特にhttp://blogs.msdn.com/calvin_hsia/archive/2004/06/30/170344.aspxによれば、そのプロセスがそのアドレススペース内ではなく、アクセス違反としてメモリに書き込もうとしているというC0000005の例外があることに気づいた。コールスタックを読み取るには?

イベントビューア内のエントリは、コールスタックを提供します。

LibFmwk UTIL_GetDateFromLogByDayDirectory(char型のconst *、クラスutilCDate &)+ 0xa26c LibFmwk UTIL_GetDateFromLogByDayDirectory(char型のconst *、クラスutilCDate &)+ 0x8af4 ! LibFmwk!UTIL_GetDateFromLogByDayDirectory(char型のconst *、クラスutilCDate &)+ 0x13a1 LibFmwk!utilCLogController :: GetFLFInfoLevel(無効)のconst + 0x1070 LibFmwk!utilCLogController :: GetFLFInfoLevel(無効)のconst + 0x186

ここで、私はメソッド名を見ていることを理解していますが、各行の最後のアドレス(例: + 0xa26c)は、そのメソッド内の特定の行または命令を指し示そうとしています。

だから私の質問は以下のとおりです。

  1. 誰もが、私はコード内のが上の転倒どのラインかを決定するために、このアドレスまたはコールスタック内の他の情報を使用する方法を知っていますか?
  2. コールスタックをよりよく理解するために読めるリソースはありますか?
  3. デバッグシンボルファイルやバイナリにアタッチすることで、コールスタックの解析に役立つフリーウェア/オープンソースツールはありますか?

編集:要求され、ここで問題を引き起こしているように見える方法があるとして :

BOOL UTIL_GetDateFromLogByDayDirectory(LPCSTR pszDir, utilCDate& oDate) 
{ 
BOOL bRet = FALSE; 

if ((pszDir[0] == '%') && 
    ::isdigit(pszDir[1]) && ::isdigit(pszDir[2]) && 
    ::isdigit(pszDir[3]) && ::isdigit(pszDir[4]) && 
    ::isdigit(pszDir[5]) && ::isdigit(pszDir[6]) && 
    ::isdigit(pszDir[7]) && ::isdigit(pszDir[8]) && 
    !pszDir[9]) 
{ 
    char acCopy[9]; 
    ::memcpy(acCopy, pszDir + 1, 8); 
    acCopy[8] = '\0'; 

    int iDay = ::atoi(&acCopy[6]); 
    acCopy[6] = '\0'; 
    int iMonth = ::atoi(&acCopy[4]); 
    acCopy[4] = '\0'; 
    int iYear = ::atoi(&acCopy[0]); 

    oDate.Set(iDay, iMonth, iYear); 

    bRet = TRUE; 
} 

return (bRet); 

}

これは私達の会社のメンバーによって10年以上前に書かれたコードであります私は、これが何をしているのか正確に知っているとは思っていませんが、ログディレクトリの名前を「Today」から特定の日付に変更するプロセスに関わっています。 %20090329配列の索引付け、memcpy、および演算子のアドレスは、それが疑わしいものに見えるようにします。

この問題は、本番システムでのみ発生するため、ここでテストシステムや開発システムで再現できなかったため、デバッガを接続することができませんでした。

非常に高く評価されました! アンディ

+1

デバッグシンボルを使用してビルドすると、バイトオフセットではなく実際の行番号が得られる可能性があります。 –

+0

それを指摘してくれてありがとう。 –

+0

渡されるpszDirの長さが10文字以上であることを確認してください。そうでない場合は間違いなくクラッシュします。 – jussij

答えて

3

これらのアドレスを実際に関数にマップする必要がある場合は、.MAPファイルを操作して、それらのアドレスが実際に指している場所を確認する必要があります。

あなたの状況では、私はむしろデバッガ(MSVSデバッガやwindbgなど)でこの問題を調査したいと思います。代わりに(クラッシュが顧客のサイトで発生した場合)、クラッシュダンプを生成してローカルで勉強することができます.Windows MiniDumpWriteDump APIまたはSysInternals ProcDumpユーティリティ(http://download.sysinternals.com/Files/procdump.zip)で実行できます。

必要なシンボルファイルがすべて生成され、使用可能であることを確認します(Windows DLLのエントリポイントも解決されるように、Microsoft Symbol Serverのパスを設定します)。

IMHOこれはあなたが必要とするウェブサイトです:http://www.dumpanalysis.org - あなたのすべての質問をカバーするのに最適なリソースです。 このPDFを見てみることを検討する - http://windbg.info/download/doc/pdf/WinDbg_A_to_Z_color.pdf

+0

これは金です!非常に興味深いリンク! – Karel

1

ポイント2と3は、簡単に答えています

第三ポイント。任意のデバッガ。それが彼らのために作られたものです。この特別な例外を打ち破るようにデバッガを設定してください。あなたはコールスタックを通して自分自身をクリックし、スタック上の異なる呼び出しを見つけることができるはずです(少なくとも、デルファイはこれを行うことができるので、ビジュアルスタジオも可能でなければなりません)。可能であれば、最適化せずにコンパイルしてください。 OllyDBGも同様に機能する可能性があります。おそらく、トレース機能と組み合わせて使用​​することができます。

第2ポイント。x86アセンブラ、リバースエンジニアリングに関するすべての情報...試してみてください:OpenRCENASM DocumentationASM Community

第1ポイント。コールスタックは関数を指示します。私は、それが順番に、または逆の順序で書かれているかどうかわからないので、最初の行が最後に呼ばれた関数または最初に呼び出された関数である可能性があります。デバッガの助けを借りてコールに従ってください。場合によっては、asmとcodeの間で変更することができます(デバッガ、マップファイルに応じて...)。ソースラーニングアセンブラをお持ちでない場合は、リバースエンジニアリングについてお読みください。サードパーティのコンポーネントで呼び出した関数のドキュメントをお読みください。おそらくあなたは前提条件を満たしていないでしょう。

あなたがプログラムの開発について少しを伝えることができた場合は(あなたが持っているか、ソースコードの一部、... ?,関与ライブラリコールです)


現在、いくつかのコード読み取り:

この関数は、ゼロ終了文字列へのポインタと日付オブジェクトへの参照を受け入れます。ポインタは有効であると見なされます。

この関数は、文字列が特定の形式(%の後に8桁の数字に続いて\ 0)であるかどうかをチェックします。そうでない場合、falseを返します。このチェック(big if)は、有効性チェックを行わずにポインタにアクセスします。長さはチェックされず、ポインターが野生のどこかを指している場合、このスペースにアクセスします。短い文字列で問題が発生するかどうかはわかりません。それは方法のためにではありません& &評価されます。

次に、スタックにいくつかのメモリが割り当てられます。文字列の数字部分がそこにコピーされ(これはOKです)、バッファは\ 0終了します。 atoisは数字を抽出します。これは、使用される開始位置が異なるため、各部分の後に\ 0終了があるために機能します。どういうわけかトリッキーだがいい。いくつかのコメントは、すべてを明確にしたでしょう。

これらの番号がオブジェクトに挿入されます。参照によって関数に渡されるため、有効である必要があります。あなたが削除されたオブジェクトへの参照を渡すことができるかどうかわかりませんが、この場合、これもあなたの問題かもしれません。

とにかく、文字列ポインタのチェックがないことを除けば、この機能は健全で問題の原因ではありません。それは例外をスローする唯一の場所です。この関数に渡される引数を検索します。彼らはいつも有効ですか?いくつかのロギングを行います。

私はDelphiのプログラマーなので、私は大きなミスを犯してはいけないと思います。もし私がした場合は、自由にコメントしてください。

+0

コードを見ていただきありがとうございます。渡されたパラメータが正しいメモリ領域を指していると仮定して、アクセス違反が発生するような方法では何も存在しない限り、私はあなたに同意します。それは私が確認する必要があるものです。私は、これらの回答を正しい回答として設定できることを願っています。 –

+0

np - 私は助けに来ました、ポイントのためではありません。 –

5

他の人はこれを明示的には言っていないが、この間に述べている。見:

LibFmwk!UTIL_GetDateFromLogByDayDirectory(char const *,class utilCDate &) + 0xa26c 

オフセット0xa26cは、関数の最後過去のやり方、巨大です。デバッガは明らかにLibFmwkの適切なシンボルを持っていないので、代わりにDLLのエクスポートに依存し、見つかった最も近いオフセットに関連するオフセットを表示します。

そう、ええ、適切なシンボルを取得し、その後、それは微風でなければなりません。 UTIL_GetDateFromLogByDayDirectoryはここでは問題ありません。

関連する問題