如何在没有调试器的情况下定位 "Invalid floating point" 异常的来源?
How to locate the origin of "Invalid floating point" exception without the debugger?
我的系统运行了几个小时都没有问题。
突然抛出invalid floating point异常
它没有发生:
- 在调试器中 运行
- 在所有计算机中
如何在没有调试器的情况下确定抛出异常的位置?
我用 Delphi 6.
通过日志记录和异常跟踪的组合。
这意味着您的系统必须使用调试信息进行部署。对你来说似乎不是问题,但有时是盒子软件的问题。
有很多工具可以做到这一点,但可能并非所有工具都兼容 Delphi-6。仅举几例:
- Delphi obtain stack trace after exception
- How can I obtain a stack trace without using third party components?
- Display the call stack in a Delphi Win32 application
- http://blog.synopse.info/post/2011/04/14/Enhanced-logging-in-SynCommons
所以你必须更改默认的异常处理程序(在 TApplication
、ExceptProc
或其他任何地方 - 源代码中的那些工具会告诉你如何做)并记录浮点异常(你现在几乎不会对所有可能的例外感兴趣。
这又带来了另一个问题:日志框架。上面的一些库已经有了,有些需要额外的库。您现在已经需要它,以后您会更需要它。
- Which logging library is better?
- Good, free Delphi logging framework
- https://mikejustin.wordpress.com/2012/09/12/delphi-and-free-pascal-logging-with-the-log4d-open-source-library/
现在您 运行 您的服务一段时间了,它会不断保存所有与 FP 相关的异常及其堆栈跟踪。如果您在禁用某些优化(如 "always generate stack frame")的情况下编译它,它可能还会显示一些局部变量和参数。
如果幸运的话,这足以让您了解错误是如何发生的。但很可能您会看到直接的错误情况,但看不到它们是如何从失败的初始假设中发展而来的。
在那种情况下,您至少会有错误的堆栈跟踪(执行路径)(或者您认为是一个类似错误的一些路径)。
那时您将主要精力转移到日志记录上。了解您的执行路径,您可以记录执行路径上所有有趣的函数参数和局部变量,并查看这些变量如何在记录异常之前获得异常值(以及如果现在发生异常,值如何正常)。
您将不得不进行多次迭代,首先将搜索向下扩展到调用堆栈,将更多参数和变量添加到日志中,并且可能包括一些不直接在调用堆栈中的并行例程到日志记录但在异常之前被调用并且在错误之前影响了局部变量值。
我的系统运行了几个小时都没有问题。
突然抛出invalid floating point异常
它没有发生:
- 在调试器中 运行
- 在所有计算机中
如何在没有调试器的情况下确定抛出异常的位置?
我用 Delphi 6.
通过日志记录和异常跟踪的组合。 这意味着您的系统必须使用调试信息进行部署。对你来说似乎不是问题,但有时是盒子软件的问题。
有很多工具可以做到这一点,但可能并非所有工具都兼容 Delphi-6。仅举几例:
- Delphi obtain stack trace after exception
- How can I obtain a stack trace without using third party components?
- Display the call stack in a Delphi Win32 application
- http://blog.synopse.info/post/2011/04/14/Enhanced-logging-in-SynCommons
所以你必须更改默认的异常处理程序(在 TApplication
、ExceptProc
或其他任何地方 - 源代码中的那些工具会告诉你如何做)并记录浮点异常(你现在几乎不会对所有可能的例外感兴趣。
这又带来了另一个问题:日志框架。上面的一些库已经有了,有些需要额外的库。您现在已经需要它,以后您会更需要它。
- Which logging library is better?
- Good, free Delphi logging framework
- https://mikejustin.wordpress.com/2012/09/12/delphi-and-free-pascal-logging-with-the-log4d-open-source-library/
现在您 运行 您的服务一段时间了,它会不断保存所有与 FP 相关的异常及其堆栈跟踪。如果您在禁用某些优化(如 "always generate stack frame")的情况下编译它,它可能还会显示一些局部变量和参数。
如果幸运的话,这足以让您了解错误是如何发生的。但很可能您会看到直接的错误情况,但看不到它们是如何从失败的初始假设中发展而来的。
在那种情况下,您至少会有错误的堆栈跟踪(执行路径)(或者您认为是一个类似错误的一些路径)。 那时您将主要精力转移到日志记录上。了解您的执行路径,您可以记录执行路径上所有有趣的函数参数和局部变量,并查看这些变量如何在记录异常之前获得异常值(以及如果现在发生异常,值如何正常)。
您将不得不进行多次迭代,首先将搜索向下扩展到调用堆栈,将更多参数和变量添加到日志中,并且可能包括一些不直接在调用堆栈中的并行例程到日志记录但在异常之前被调用并且在错误之前影响了局部变量值。