0

我们有一个围绕 VB/C++ 代码构建的自定义应用程序。此代码将运行数天、数周、数月,而不会引发异常错误。

我正在尝试了解有关如何引发此错误的更多信息,以及如何解释(如果可以的话)引发异常时列出的错误。我已经搜索了一些信息并阅读了 Microsoft 提供的错误描述,但我仍然坚持解决在蓝月亮中发生的事情的任务。没有已知的与软件的交互会导致这种情况,并且似乎是随机发生的。

第一个异常是根本原因吗?一直到堆栈调用吗?任何人都可以提供有关如何阅读这些代码的任何见解,以便我可以解释我实际需要查看的位置。

有关阅读异常或对其进行任何使用,然后对其进行故障排除的任何信息或指导都会有所帮助。下面的测试是在引发事件时从 Windows 日志中复制的。

提前感谢您的帮助。

Application: Epic.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: System.AccessViolationException [![enter image description here][1]][1]
at MemMap.ComBuf.IsCharAvailable(Int32) 
at HMI.frmPmacStat.RefreshTimer_Elapsed(System.Object, System.Timers.ElapsedEventArgs) 
at System.Timers.Timer.MyTimerCallback(System.Object) 
at System.Threading.TimerQueueTimer.CallCallbackInContext(System.Object) 
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, 
System.Threading.ContextCallback, System.Object, Boolean) 
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, 
System.Threading.ContextCallback, System.Object, Boolean) 
at System.Threading.TimerQueueTimer.CallCallback() 
at System.Threading.TimerQueueTimer.Fire() 
at System.Threading.TimerQueue.FireQueuedTimerCompletion(System.Object) 
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 
at System.Threading.ThreadPoolWorkQueue.Dispatch() 
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

在此处输入图像描述在此处输入图像描述

4

2 回答 2

2

由于执行 throw 表达式,c++ 运行时环境会抛出异常,还有其他类型的错误是由操作系统或硬件捕获您的指令引起的。对内存的无效访问通常不会由 c++ 中的代码抛出,而是评估试图访问无效地址处内存的表达式的副作用,导致操作系统向进程发出信号,通常会杀死它。因为它在 C++ 之外,它往往是特定于平台的,但典型的错误是:

  • 读取空指针
  • 使用指向已删除对象的指针
  • 超出数组的有效元素范围
  • 在 STL 容器中使用无效的迭代器

一般来说,您可以在运行时测试 null 和数组边界,以便在问题发生之前检测到问题。使用悬空指针更难追踪,因为从删除到误用该指针之间的时间可能很长,而且如果没有内存调试器(例如 valgrind),很难找到它发生的原因。使用智能指针而不是原始指针有助于缓解内存管理不善的问题,并有助于避免此类错误。

无效的迭代器是一般悬空指针问题的子集,但很常见,值得一提的是它们自己的类别。了解您的容器以及哪些操作使它们无效是至关重要的,一些实现可以在“调试模式”下编译,这有助于检测无效迭代器的使用。

于 2017-09-13T14:51:16.417 回答
1

正如其他人所指出的,如果不深入研究代码和运行测试(自动或手动),这种类型的错误很难识别。您可以拉出并仍然复制它的系统组件越多越好。分而治之是你的朋友。

除此之外,这一切都取决于您解决这个问题的重要性以及您愿意付出多少努力。至少有三类工具可以帮助解决此类间歇性问题:

  1. 在应用程序运行时跟踪潜在错误的应用程序监视器。这些往往会显着减慢您的程序(减慢 10 倍或更多)。示例包括:
    1. Microsoft 的应用程序验证程序
    2. 开源和跨平台的Dr. Memory
    3. 谷歌的Crashpad。与前两个程序不同,这个程序需要检测您的代码。它也(据称 - 没有尝试过)更容易与Backtrace 的商业集成等帮助程序一起使用,以分析 Crashpad 输出
    4. Google 的Sanitizers - 免费,有些内置在 gcc 和 clang 中。Address Sanitizer还有一个Windows 端口,但粗略一看,它可能有点像二等公民。
    5. 如果你可以运行和重现它也可以在 Linux 上运行,你可以使用valgrindrr(请参阅此 CppCast ep),它是 gdb 的免费扩展,可记录和重播您的程序,因此您可以记录崩溃的调试会话,然后单步执行以查看问题所在;和/或UndoDB和 Undo 软件的朋友,这是一个更复杂的商业产品,如 rr。
  2. 代码的静态分析。这是一组用于查找代码中常见错误的工具。它通常具有较低的信噪比,因此如果您在现有的大型项目上运行它,有很多小事情需要挖掘(如果可能,最好从一开始就使用这些东西开始一个项目)。也就是说,许多警告是无价的。例子:
    1. 大多数编译器都内置了此功能的子集。如果您使用的是 Visual Studio,请将/W4 /WXC++ 代码添加到编译标志以强制发出最大警告,然后修复所有警告。对于 gcc 和 clang,添加“-Wall -Wpedantic -Werror”以强制不发出警告。
    2. PVS-工作室(商业)
    3. PC-Lint(商业)
  3. 如果您可以检测代码以编写日志消息,那么Debugview++之类的东西可能会有所帮助。

如果你有多线程,事情会变得更难,看起来你这样做了,因为不确定性变得更难跟踪,引入了新的可能错误类别,并且上述一些工具无法正常工作(例如,我认为 rr 只是单线程的)。除了像 Visual Studio 这样的完整 IDE 之外,您还需要使用 Intel 的Inspector(以前称为 Intel Thread Checker),或者在 Linux、Valgrind 的HelgrindDRD和 ThreadSanitizer(在上面的清理程序中,但也只有 Linux AFAIK)。但希望这份清单能给你一个开始的地方。

于 2017-09-13T15:41:47.617 回答