Странные исключения в коде фреймворка .Net CF под WinCE 6.0 R3

В нашем приложении .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 МБ.


person Steve Hiner    schedule 11.02.2010    source источник
comment
Можете ли вы включить код, который вызывает ваш метод AddParm, а также полное сообщение об исключении со всеми подробностями (и полный стек).   -  person Simon P Stevens    schedule 11.02.2010
comment
На самом деле у меня больше нет полного стека. Все вызовы выше того, что я показал, являются внутренними методами. Причина, по которой у меня его больше нет, заключается в том, что эта ошибка возникает из-за WinCE и отображается на экране - поскольку она не обнаружена, она не регистрируется, и с тех пор я несколько раз перезагружала установку, тщетно пытаясь заставить ее вновь случилось.   -  person Steve Hiner    schedule 11.02.2010


Ответы (3)


Оказалось, что это была ошибка переполнения буфера в нативном коде. код С# вызывал метод и передавал массив байтов с 8 элементами. Код C++ заполнял 6 байтов, а затем перезаписывал еще 6 нулями. Этот метод вызывался достаточно часто и каждый раз перезаписывал 4 байта памяти нулями. Дох!

Это объясняет совершенно странные ошибки, вероятно, была перезапись битов .Net framework в памяти.

Нужно следить за этими взаимодействиями между управляемым и неуправляемым кодом. К счастью для меня, рассматриваемый код не был моим.

(Не уверен, что я должен принять свой собственный ответ в качестве ответа, поскольку никто не мог ответить на него, не глядя на нашу кодовую базу. Точно так же я не должен отмечать ответ JaredPar как «ответ», поскольку проблема заключалась в повреждении памяти, а не в действительности. нативное исключение. Думаю, я все равно опубликую это, так как, возможно, у кого-то еще будет похожая ситуация, и, возможно, они рассмотрят взаимодействие с нативным кодом. Администраторы: не стесняйтесь удалять эту тему, если вы считаете, что это лучше.)

person Steve Hiner    schedule 22.02.2010
comment
Вы должны принять свой собственный ответ;) Кстати, я думаю, что у меня те же проблемы, это подтверждает некоторые мои подозрения. Спасибо. - person Stormenet; 20.10.2010
comment
1) Мне нравится, как на это есть ТАК ответ. 2) Я ненавижу, что мне приходится искать его через 5 лет после факта. - person OldTinfoil; 02.12.2015

Я думаю, что сообщение о вашей второй трассе является наиболее поучительным

В BbCore.exe возникло собственное исключение.

Похоже, что это собственное исключение, а не управляемое исключение, которое отключает ваш продукт. Собственные исключения, как правило, не перехватываются управляемым кодом. В некоторых случаях это возможно, но, вообще говоря, нативные исключения фатальны.

Вы можете попробовать использовать блок catch для исключений SEH и посмотреть, сработает ли это.

try { 
  ...
} catch { 

}

Но в целом, если нативный код выбрасывает, ваше приложение нестабильно и должно падать.

person JaredPar    schedule 11.02.2010
comment
Итак, включение улова без (Exception ex) может перехватывать неуправляемые исключения? Я этого не понимал. Это имеет смысл, поскольку (Exception ex) будет перехватывать только ошибки, полученные из Exception. Отличный совет! - person Steve Hiner; 11.02.2010
comment
Я думаю, что я в порядке, если он падает, но я хотел бы, по крайней мере, зарегистрировать его, чтобы я мог узнать, какой ввод привел к падению. В тех случаях, когда это происходило, у меня нет оснований полагать, что ввод был бы чем-то иным, кроме того, что мы создаем в коде, и ничем не отличался бы от каждого другого вызова метода. Я начинаю задаваться вопросом, повреждена ли память. Если я увижу ввод, я узнаю, должен ли ввод даже вызвать его сбой, и если ввод отличается от того, что отправил другой код. - person Steve Hiner; 11.02.2010

Я просто столкнулся с этой ошибкой в ​​​​новой версии моего приложения. Пробовал несколько вещей, в последнем я удалил изображения 256x256 и 64x64 в значке формы, которые заменены в этой версии, и это сработало.

person deerchao    schedule 21.05.2014