RednaxelaFX 发表于 2013-2-5 01:20:01

nop对程序语义的影响

原本我一直以为nop对程序语义应该没什么影响的,呜,我错了。

之前一直觉得很奇怪,为什么不开/o(/optimize,优化)开关来编译C#程序的话,生成的IL代码里会有很多nop。后来才知道那些nop是在一些语句或者表达式片段的边界放的,目的是为了提供更好的调试体验:有些代码被编译之后可能会变得比较难下断点,所以插入nop来占位,使得原本难下断点的地方能被设置断点。

但是插入nop的代价不只是使程序的运行速度降低;更糟糕的是,它可能会改变程序的语义使本来应该正常的程序变得无法正确运行。
Eric Lippert在去年的一篇blog里提到了这点。他举的例子是C#里的lock语句:
lock(expression) statement
会被编译成类似这样:
temp = expression;System.Threading.Monitor.Enter(temp); try { statement } finally { System.Threading.Monitor.Exit(temp); }
这本来没什么问题,但是当C#编译器在Enter()与try之间插入nop时问题就来了:如果另外一个线程在当前线程刚获取锁在nop的时候引发了线程终止异常,那么finally子句就永远不会被执行,于是就是……死锁。

据说这个问题在C# 3.0里也没解决。不过还好遇到这种问题的可能性很小。
Hmm。果然遇上多线程之后很多“常识”都得重新想想。
页: [1]
查看完整版本: nop对程序语义的影响