2010-02-11 74 views
3

在我们的.CF应用程序中,我们从部分代码中发现了不应该有问题的奇怪错误。例如,下面的代码:WinCE 6.0下.Net CF框架代码中的奇怪例外R3

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足够防御,以便在分割调用之前捕获任何潜在问题。由于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() 

的应用2引用是由于使用OpenNetCF.Windows的.Forms.dll。我从来没有在代码的那部分看到崩溃,它基本上是随机的。

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

从R2升级到WinCE 6 R3平台构建器后,看起来这些更为常见。我不确定他们是否曾经在R2下发生过,但他们肯定不太经常。即使现在它们并不总是发生 - 我无法可靠地再现它们。

任何想法?为什么框架的核心部分会抛出不被Try..Catch捕获的错误?

附加信息:看来我忽略了一条重要信息。 ExceptionCode被列为0x80000002,这看起来是一个本机内存不足异常。根据垃圾收集器,我们的应用很少使用超过1MB的内存。根据coredll.dll的GlobalMemoryStatus,系统的典型内存负载约为29%(在57MB中有41MB空间)。那里有没有好的实用程序能够监视和记录整个系统内存的使用情况?我开始怀疑我用来衡量内存使用的技术是否不如我想像的那么精确。使用OpenNetCF.ToolHelp.ProcessEntry。GetProcesses()显示我们的进程使用大约3.6MB和NK.exe使用大约2.5 MB。

+0

您能否包含调用您的“AddParm”方法的代码,以及包含所有细节(以及完整堆栈)的完整异常消息。 – 2010-02-11 18:38:10

+0

我实际上没有足够的堆栈了。上面显示的所有电话都是内部方法。我没有它的原因是因为这个错误来自WinCE并且显示在屏幕上 - 因为它没有被捕获它不会被记录,并且我已经多次尝试重新启动钻井平台来徒劳地尝试获取它再次发生。 – 2010-02-11 20:53:21

回答

3

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

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

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

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

+0

你应该接受你自己的答案;)顺便说一句,我认为我有同样的问题,这证实了我的一些怀疑。谢谢。 – Stormenet 2010-10-20 13:21:42

+0

1)我喜欢这样的答案。 2)我讨厌在事实发生5年后我不得不寻找它。 – OldTinfoil 2015-12-02 15:30:04

1

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

上BbCore.exe

发生了机异常看来,这是一个机异常不是一个托管异常是取下你的产品。原生异常是通用规则,不能由托管代码捕获。在某些情况下是可能的,但一般来说,本地例外是致命的。

您可以尝试使用SEH异常的catch块并查看是否有效。

try { 
    ... 
} catch { 

} 

但一般来说,如果本地代码抛出你的应用是不稳定的,它应该崩溃。

+0

因此,在没有(Exception ex)的情况下进行catch可能会捕获非托管异常?我没有意识到这一点。这很有意义,因为(Exception ex)只会捕获从Exception中派生的错误。伟大的提示! – 2010-02-11 20:50:06

+0

我猜如果它崩溃,我可以,但我至少要记录它,以便我可以找出输入是什么导致它崩溃。发生的时代我没有理由相信输入可能是除了我们在代码中创建的东西之外的任何东西,并且与我们每次调用方法时都没有什么不同。我开始怀疑内存是否损坏。如果我能看到输入,我会发现输入是否会导致输入崩溃,以及输入是否与其他代码发送的内容不同。 – 2010-02-11 20:51:18

0

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