在我们的.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。
答案 0 :(得分:3)
原来这是本机代码中的缓冲区溢出错误。 C#代码调用一个方法并传递一个包含8个元素的字节数组。 C ++代码填充6个字节,然后用零覆盖另外6个字节。每次用零覆盖4个字节的内存时,这个方法被调用了很多次。卫生署!
这解释了完全奇怪的错误,可能是在内存中覆盖了.Net框架的一些内容。
要注意托管代码和非托管代码之间的这些交互。对我来说幸运的是,有问题的代码不是我的。
(不确定我是否应该接受我自己的答案作为答案,因为没有人可以在不查看我们的代码库的情况下回答这个问题。同样我不应该将JaredPar的答案标记为“答案”,因为问题是内存损坏,不是真正的本机异常。我想我会发布这个,因为也许其他人会有类似的情况,也许他们会调查与本机代码的交互。管理员:如果你觉得最好,可以随意删除这个帖子。)
答案 1 :(得分:1)
我认为第二条跟踪上的消息是最有启发性的
BbCore.exe上发生了本机异常
它似乎是一个原生异常,而不是一个正在取消产品的托管异常。本机异常通常是托管代码无法捕获的规则。在某些情况下是可能的,但一般来说,本地例外是致命的。
您可以尝试将catch块用于SEH异常,看看是否有效。
try {
...
} catch {
}
但一般情况下,如果本机代码丢失你的应用程序是不稳定的,它应该崩溃。
答案 2 :(得分:0)
我刚刚在我的应用程序的新版本中遇到此错误。 尝试了几件事,最后,我删除了在此版本中替换的表单图标中的256x256和64x64图像,并且它有效。