私たちの .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 が表示されます。