简体   繁体   English

调试优化代码有哪些陷阱?

[英]What are the pitfalls of debugging optimized code?

This question is a follow up of this one where the consensus was that the value of *this* pointer is not correct because of optimization but what does not correct means? 这个问题是一个跟进一个地方的共识是, the value of *this* pointer is not correct because of optimization但到底是什么not correct的手段?

  1. That we can't trust the value of this pointer so we should throw it out all together when we debug a release build? 我们不能信任指针的值,因此在调试发行版时应该将其全部丢弃吗?
  2. That this pointer may change its value as we debug a release build and that's okay because its optimized code, it may not mean any harm? 在我们调试发行版时, 指针可能会更改其值,这没关系,因为其优化的代码可能并不意味着任何危害?
  3. this pointer still points to a valid memory block of the object and the fact it changes is cause of concern even when its optimized code. 指针仍然指向对象的有效内存块,并且即使更改了其优化代码,也要引起关注。
  4. There is mismatch between the actual code and the optimized generated code, this is why the debugger may show incorrect values or values of variables may change abruptly? 实际代码和优化的生成代码之间不匹配,这就是为什么调试器可能显示错误的值或变量的值可能突然改变的原因? I could understand if debugger shows incorrect values but why should these values change? 我可以理解调试器显示的值是否不正确,但是为什么这些值应该更改?

How do we debug optimized code? 我们如何调试优化的代码? A lof of times for exmaple with WinDbg we peek into pointers, objects layouts, stack pointers even instruction pointers..does it mean we can't rely on these values because it's an optimized code? 我们用WinDbg花了很多时间来窥探指针,对象布局,堆栈指针甚至指令指针..这是否意味着我们不能依赖这些值,因为它是优化的代码? What can we rely on and what not? 我们可以依靠什么而不是什么?

IIRC, in VC++ this is passed to functions as register ECX , so the debugger just assumes that ECX is this , just a cast away. IIRC,在VC ++中, this作为寄存器ECX传递给函数,因此调试器仅假定ECX thisECX 抛弃。 That is this is the same as (CADOCommand*)ECX . 也就是说this是一样的(CADOCommand*)ECX

In debug builds that is fine because registers are not reused, but in release builds ECX is reused as any other register. 在调试版本中,这很好,因为不重用寄存器,但是在发行版本中, ECX与其他任何寄存器一样被重用。 Thus the debugger loses track of the actual this or anything pointed to by it. 因此,调试器无法跟踪实际的this或它所指向的任何内容。 The code will still be correct, of course, only the debugger is affected. 该代码仍然是正确的,当然,仅调试器会受到影响。

Actually ECX must be overwritten each time a member function of other class is called. 实际上,每次调用其他类的成员函数时,必须重写ECX For example: 例如:

m_pCommand.CreateInstance(__uuidof(Command));

Will be compiled to something like: 将被编译为以下内容:

PUSH ECX ; push this into the stack
MOV ECX, &m_pCommand
PUSH __uuidof(command) ; a constant maybe?
CALL CCommand::CreateInstance
POP ECX  ; restore this

Note how, if the compiler determines that the current this is no longer needed, then it may omit the PUSH/POP ECX . 注意如何,如果编译器确定当前this不再需要,则可以省略PUSH/POP ECX

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM