В нашем приложении .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. Трассировка стека показывает:
at ArrayList.InternalSetCapacity(Int32 value, Boolean updateVersion) at ArrayList.EnsureCapacity(Int32 min) at ArrayList.Add(Object value) at String.Split(Char[] separator) at AddParm(String str)
Это происходит в рабочем потоке.
Я зарегистрировал обработчик с AppDomain.CurrentDomain.UnhandledException в Main, но он также не перехватывает исключение.
К сожалению, в появившемся диалоговом окне ошибки WinCE не указывается тип ошибки и не выдается сообщение об ошибке, а только то, что это было в mscoree3_5.dll и трассировке стека.
Мы создаем значения, которые анализируются AddParm, и я думаю, что AddParm является достаточно защитным, чтобы обнаруживать любые потенциальные проблемы до вызова Split. Из-за того, как вызывается AddParm, он никогда не будет вызываться с нулевой строкой. Несмотря на то, что я не верю, что AddParm когда-либо может быть вызван с чем-то недопустимым, Try...Catch, обертывающий вызов, всегда должен перехватывать исключение, но это не так.
Точно так же мы также видели неперехваченные ошибки, подобные этой:
A native exception has occurred on BbCore.exe At RuntimeType.InternalGetField(rt…) At RuntimeType.InternalGetField(rt…) At SRSupport.GetString() At SRSupport.GetString() At IPAddress.Parse(String ipString)
Вот полная трассировка стека, полученная этим утром:
At CurrentSystemTimeZone.GetDaylightChanges(Int32 year) At CurrentSystemTimeZone.GetUtcOffsetFromUniversalTime(DateTime time, Boolean& isAmbiguousLocalDst) At CurrentSystemTimeZone.ToLocalTime(DateTime time) At DateTime.ToLocalTime() At DateTime.get_Now() At MainLoop.timer1_Tick(Object sender, EventArgs e) At Timer._WnProc(WM wm, Int32 wParam, Int32 lParam) At ApplicationThreadContext._InternalContextMessages(WM wm, Int32 wParam, Int32 lParam) At NativeMethods.GetMessage(MSG& lpMsg, IntPtr hWnd, UInt32 wMsgFilterMin, UInt32 wMsgFilterMax) At Application2.Pump() At Application2.RunMessageLoop(Boolean showForm) At Application2.Run(Form mainForm, Boolean runAsSingletonApp, Boolean displayMainForm) At Startup.Main()
Ссылки на Application2 связаны с использованием OpenNetCF.Windows.Forms.dll. Я никогда не видел сбоя в этой части кода, он в основном случайный.
Это еще один случай, когда IPAddress.Parse вызывается из Try...Catch, который перехватывает все типы исключений. В этом случае я полагаю, что Parse можно было вызвать с пустой строкой, но я не понимаю, почему он появился как необработанное исключение и даже не был пойман нашим обработчиком необработанных исключений, а вместо этого был пойман WindowsCE обработчик исключений и вызвал сбой всего приложения.
Похоже, что они более распространены, так как мы обновили сборщик платформ WinCE 6 R3 с R2. Я не уверен, что они когда-либо случались под R2, но они определенно были менее частыми. Даже сейчас они не всегда случаются - я не могу их достоверно воспроизвести.
Любые идеи? Почему основные части фреймворка выдают ошибки, которые не перехватывает Try..Catch?
Дополнительная информация. Похоже, я упустил важную информацию. ExceptionCode указан как 0x80000002, что, по-видимому, является собственным исключением нехватки памяти. Согласно сборщику мусора, наше приложение редко использует больше 1 МБ памяти. Согласно GlobalMemoryStatus coredll.dll типичная загрузка памяти для системы составляет около 29% (свободно 41 МБ из 57 МБ). Существуют ли какие-либо хорошие утилиты, которые могли бы отслеживать и регистрировать общее использование системной памяти с течением времени? Я начинаю задаваться вопросом, не так ли точны методы, которые я использую для измерения использования памяти, как я думал. Использование OpenNetCF.ToolHelp.ProcessEntry.GetProcesses() показывает, что наш процесс использует около 3,6 МБ, а NK.exe — около 2,5 МБ.