Debug 配置下的调试, 因为开发环境默认设置值的缘故(就是默认不打开编译器的优化), 没碰到过问题.
在Release配置下, 产品已经布署出去, 到了QA手里报出bug 来, 这时通过远程调试来跟踪问题时, 却经常发现有些变量的值在运行时看不了, 对调试是一种极大的障碍.
我得到的粗浅印象是, 对于托管代码, 它优不优化应该对可调试性影响很小, 多小? 远小于native代码是否优化的影响.
Tools/Options/Debugging/General下有一项
"Suppress JIT optimization on module load(managed only)"
是有用的, 但是往往作用有限, 因为它只有在你attach了被调试过程之后才加载的Assembly才会被禁止优化.
为了达到模块不被优化的目的, 我在Main函数的第一句话加了个对话框, 此时Attach被调试进程, 但往往还是为时已晚, 因为有一些静态变量/静态构造函数之间的依赖关系, 在进入Main之前就可以需要Load一些另外的模块.
找到了解决这一问题的办法:
如果你的模块名是 myApp.exe 或 myApp.dll
在其同目录下放置一个名为 myApp.ini的文件, 内容如下:
[.NET Framework Debugging Control]
GenerateTrackingInfo=1
AllowOptimize=0
通过 File Monitor观察, 有了该文件之后, 启动主程序时, 的确这个ini文件会被自动拜访. 可能是CLR运行时做的, 我没有继续跟踪下去.
实际用.NET对程序的可调试性的观察也证实: 这个办法有效, 对于Release配置, 编译时打开了优化的情况, 确确实实是有效的.
另外, 找到一个可以在源代码中直接控制可调试性的办法:
[assembly: System.Diagnostics.DebuggableAttribute(true, true) ]
效果等同于上面, 但是这个做法不好, 因为对于Release版它总会降低运行性能.
而上面的做法则只有开发者想调试时才生成这个INI文件, 不调试时可以移除该文件, 这样不会影响程序运行.
csc /optimize- 与 csc 不跟/optimize选项时, 用reflector观察assembly的Attribute, 都是
[assembly:
Debuggable(DebuggableAttribute.DebuggingModes.DisableOptimizations |
DebuggableAttribute.DebuggingModes.EnableEditAndContinue |
DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints |
DebuggableAttribute.DebuggingModes.Default)]
但打开 csc /optimize+之后是
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints |
DebuggableAttribute.DebuggingModes.Default)]
而显式地在代码中指定了
[assembly: System.Diagnostics.DebuggableAttribute(true, true) ]
之后, 不管取值如何, 都好象忽略了来自编译器的影响.
第一次看到这个INI文件的机制时, 微软的文档并未明确说明是在程序编译出来之前还是之后发生作用. 看来这个INI影响的是运行时的CLR. 影响的是JIT, 而不是编译器.
下面看一个JIT执行了优化时给调试造成不便的情况和使用了INI文件之后对比的情况:
看一下 File Monitor对INI文件的监控结果:
阅读(1464) | 评论(0) | 转发(0) |