3

私たちの .Net CF アプリでは、コードの一部で問題が発生するはずのない奇妙なエラーが発生しています。たとえば、次のコード:

public void AddParm(string str)
{
    string[]        pair = str.Split('=');
    string          key = pair[0].Trim();
    string          value = pair.Length > 1 ? pair[1] : "";
    if (key.Length > 0)
    {
        if (_parmTable.ContainsKey(key))
            _parmTable[key] = value;
        else
            _parmTable.Add(key, value);
    }
}

AddParm() を呼び出すルーチンは、Try...Catch ブロックで呼び出しをラップし、すべての例外タイプをキャッチします。

public void Unpack(string txn)
{
    try
    {
        // split out strings like: "EVENTLABEL:x=1,y=2,z=3"
        char chEvent = ':';
        char chSeparator = ',';

        _parmTable = new Hashtable();

        int iEvent = txn.IndexOf(chEvent);

        if (iEvent == -1)
            _eventLabel = txn;
        else
        {
            _eventLabel = txn.Substring(0, iEvent);

            string parms = txn.Substring(iEvent + 1).TrimEnd('\n');
            string[] items = parms.Split(chSeparator);

            if (items.Length <= 0)
                AddParm(parms);
            else
                foreach (string item in items)
                    AddParm(item);
        }
    }
    catch (Exception ex)
    {
        AppLog.logException(string.Format("UnpackedTask.Unpack: Error parsing '{0}'", txn), ex);
    }
}

エラーが発生したモジュールを mscoree3_5.dll としてリストするコアの未処理の例外を取得しました。スタック トレースは次を示します。

ArrayList.InternalSetCapacity (Int32 値、ブール値の updateVersion) で
ArrayList.EnsureCapacity (Int32 分) で
ArrayList.Add (オブジェクト値) で
String.Split (Char[] セパレーター) で
AddParm (文字列 str) で

これは、ワーカー スレッドで発生しています。

メインで AppDomain.CurrentDomain.UnhandledException を使用してハンドラーを登録しましたが、例外もキャッチしません。

残念ながら、表示される WinCE エラー ダイアログには、エラーの種類やエラー メッセージが表示されず、エラーが mscoree3_5.dll とスタック トレースにあったことがわかります。

AddParm によって解析される値を作成します。AddParm は十分に防御的で、Split 呼び出しの前に潜在的な問題をキャッチできると思います。AddParm の呼び出し方法により、null 文字列で呼び出されることはありません。AddParm が無効なもので呼び出されることはないと思いますが、呼び出しをラップする Try...Catch は常に例外をキャッチする必要がありますが、そうではありません。

同様に、次のようなキャッチされていないエラーも確認されています。

BbCore.exe でネイティブ例外が発生しました

RuntimeType.InternalGetField(rt…) で
RuntimeType.InternalGetField(rt…) で
SRSupport.GetString() で
SRSupport.GetString() で
IPAddress.Parse(String ipString) で

今朝の完全なスタック トレースを次に示します。

At CurrentSystemTimeZone.GetDaylightChanges(Int32 年)
At CurrentSystemTimeZone.GetUtcOffsetFromUniversalTime(DateTime time, Boolean& isAmbiguousLocalDst)
At CurrentSystemTimeZone.ToLocalTime(DateTime time)
At DateTime.ToLocalTime()
DateTime.get_Now() で
MainLoop.timer1_Tick(オブジェクト送信者、EventArgs e) で
At Timer._WnProc(WM wm, Int32 wParam, Int32 lParam)
ApplicationThreadContext._InternalContextMessages(WM wm, Int32 wParam, Int32 lParam) で
NativeMethods.GetMessage(MSG& lpMsg, IntPtr hWnd, UInt32 wMsgFilterMin, UInt32 wMsgFilterMax) で
Application2.Pump() で
Application2.RunMessageLoop(Boolean showForm) で
Application2.Run(Form mainForm、Boolean runAsSingletonApp、Boolean displayMainForm) で
Startup.Main() 時

Application2 の参照は、OpenNetCF.Windows.Forms.dll の使用によるものです。コードのその部分でクラッシュは見たことがありません。基本的にランダムです。

これは、すべての例外タイプをキャッチする Try...Catch 内から IPAddress.Parse が呼び出される別のケースです。その場合、Parse が空の文字列で呼び出される可能性があると思いますが、なぜそれが未処理の例外として表示され、未処理の例外ハンドラーによってもキャッチされず、代わりに WindowsCE によってキャッチされたのか理解できません。例外ハンドラーが原因で、アプリ全体がクラッシュしました。

R2 から WinCE 6 R3 プラットフォーム ビルダーに更新して以来、これらはより一般的なようです。それらが R2 で発生したかどうかはわかりませんが、確かに頻度は低くなりました。現在でも、常に発生するとは限りません。確実に再現することはできません。

何か案は?フレームワークのコア部分が Try..Catch でキャッチされないエラーをスローするのはなぜですか?

追加情報: 重要な情報を書き忘れていたようです。ExceptionCode は 0x80000002 としてリストされており、ネイティブのメモリ不足例外のようです。ガベージ コレクターによると、アプリが 1 MB を超えるメモリを使用することはめったにありません。coredll.dll の GlobalMemoryStatus によると、システムの一般的なメモリ負荷は約 29% (57MB のうち 41MB が空いている) です。システムメモリの総使用量を経時的に監視および記録できる優れたユーティリティはありますか? メモリ使用量を測定するために使用している手法が、思ったほど正確ではないのではないかと思い始めています。OpenNetCF.ToolHelp.ProcessEntry.GetProcesses() を使用すると、約 3.6 MB を使用するプロセスと約 2.5 MB を使用する NK.exe が表示されます。

4

3 に答える 3

3

ネイティブ コードのバッファ オーバーラン エラーであることが判明しました。C# コードはメソッドを呼び出し、8 つの要素を持つバイト配列を渡していました。C++ コードは 6 バイトを埋めてから、別の 6 バイトをゼロで上書きしていました。このメソッドはかなり頻繁に呼び出され、そのたびに 4 バイトのメモリがゼロで上書きされていました。どっ!

これは、まったく奇妙なエラーを説明しています。おそらく、メモリ内の .Net フレームワークのビットを上書きしていたのでしょう。

マネージド コードとアンマネージド コードの間の相互作用に注意する必要があります。幸いなことに、問題のコードは私のものではありませんでした。

(コードベースを見ずに誰もこれに答えることができなかったので、私自身の答えを答えとして受け入れる必要があるかどうかはわかりません。同様に、JaredParの答えを「答え」としてマークするべきではありません。問題はメモリの破損であり、実際にはネイティブ例外. おそらく他の誰かが同様の状況にあり、ネイティブコードとの相互作用を調査する可能性があるため、とにかくこれを投稿すると思います. 管理者: それが最善だと思う場合は、このスレッドを自由に削除してください.)

于 2010-02-22T23:18:37.797 に答える
1

2番目のトレースのメッセージが最も有益だと思います

BbCore.exe でネイティブ例外が発生しました

製品をダウンさせているのは、管理された例外ではなく、ネイティブの例外であるようです。ネイティブ例外は、原則としてマネージ コードではキャッチできません。場合によっては可能ですが、一般的にネイティブ例外は致命的です。

SEH 例外に catch ブロックを使用してみて、それが機能するかどうかを確認できます。

try { 
  ...
} catch { 

}

しかし一般的に、ネイティブ コードがスローしている場合、アプリケーションは不安定であり、クラッシュするはずです。

于 2010-02-11T18:41:13.510 に答える