WinCE 6.0 R3下的.Net CF框架代码中的奇怪例外

时间:2010-02-11 18:31:41

标签: .net compact-framework windows-ce unhandled-exception

在我们的.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)

这发生在工作线程上。

我在Main中注册了一个带有AppDomain.CurrentDomain.UnhandledException的处理程序,但它也没有捕获异常。

不幸的是,出现的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。我从未在代码的那一部分看到崩溃,它基本上是随机的。

这是另一种情况,其中从Try ... Catch中捕获IPAddress.Parse,捕获所有异常类型。在那种情况下,我相信Parse可能被一个空字符串调用,但我不明白为什么它出现了一个未处理的异常,甚至没有被我们未处理的异常处理程序捕获,而是被WindowsCE捕获异常处理程序并导致整个应用程序崩溃。

似乎这些更常见,因为我们从R2更新到WinCE 6 R3平台构建器。我不确定他们是否曾经在R2下发生,但他们肯定不那么频繁。即使是现在,它们并不总是发生 - 我无法可靠地再现它们。

有什么想法吗?为什么框架的核心部分会抛出Try..Catch无法捕获的错误?

额外信息:看来我遗漏了一条重要的信息。 ExceptionCode列为0x80000002,它似乎是本机内存不足异常。根据垃圾收集器,我们的应用程序很少使用超过1MB的内存。根据coredll.dll的GlobalMemoryStatus,系统的典型内存负载约为29%(57MB中有41MB空闲)。是否有任何好的实用程序可以监视和记录系统内存总使用量?我开始怀疑我用来测量内存使用的技术是不是像我想的那么准确。使用OpenNetCF.ToolHelp.ProcessEntry.GetProcesses()显示我们使用大约3.6MB的进程和使用大约2.5 MB的NK.exe。

3 个答案:

答案 0 :(得分:3)

原来这是本机代码中的缓冲区溢出错误。 C#代码调用一个方法并传递一个包含8个元素的字节数组。 C ++代码填充6个字节,然后用零覆盖另外6个字节。每次用零覆盖4个字节的内存时,这个方法被调用了很多次。卫生署!

这解释了完全奇怪的错误,可能是在内存中覆盖了.Net框架的一些内容。

要注意托管代码和非托管代码之间的这些交互。对我来说幸运的是,有问题的代码不是我的。

(不确定我是否应该接受我自己的答案作为答案,因为没有人可以在不查看我们的代码库的情况下回答这个问题。同样我不应该将JaredPar的答案标记为“答案”,因为问题是内存损坏,不是真正的本机异常。我想我会发布这个,因为也许其他人会有类似的情况,也许他们会调查与本机代码的交互。管理员:如果你觉得最好,可以随意删除这个帖子。)

答案 1 :(得分:1)

我认为第二条跟踪上的消息是最有启发性的

  

BbCore.exe上发生了本机异常

它似乎是一个原生异常,而不是一个正在取消产品的托管异常。本机异常通常是托管代码无法捕获的规则。在某些情况下是可能的,但一般来说,本地例外是致命的。

您可以尝试将catch块用于SEH异常,看看是否有效。

try { 
  ...
} catch { 

}

但一般情况下,如果本机代码丢失你的应用程序是不稳定的,它应该崩溃。

答案 2 :(得分:0)

我刚刚在我的应用程序的新版本中遇到此错误。 尝试了几件事,最后,我删除了在此版本中替换的表单图标中的256x256和64x64图像,并且它有效。