5

I am debugging a crash and I noticed as a step through the debugger, this pointer changes its value and after 3 steps it finally get the value 0x00000001 and application crashes.

Now the 0x00000001 value is obviously wrong but should I really expect this value to change as I step through the debugger?

Below is the constructor I am debugging where it crashes. I have included the value of this pointer in comments with each step and as you can see it jumps around quite a bit.

CADOCommand::CADOCommand(CADODatabase* pAdoDatabase, CString strCommandText, int nCommandType)
{
    m_pCommand = NULL;
    m_pCommand.CreateInstance(__uuidof(Command)); // this = 0x515f9d10
    m_strCommandText = strCommandText; // this = 0x2c0c0ee8
    m_pCommand->CommandText = m_strCommandText.AllocSysString(); // this = 0x515f9d20
    m_nCommandType = nCommandType; // this = 0x70847a55
    m_pCommand->CommandType = (CommandTypeEnum)m_nCommandType; // this = 0x00000001
    m_pCommand->ActiveConnection = pAdoDatabase->GetActiveConnection(); 
    m_nRecordsAffected = 0;
}

Is there any circumstances where value of this could or should change as we step through the code in a given member function?

Update

I must add for record and in response to several comments, I was debugging release build but when I debugged the same function in debug build, the value of this didn't change after all.

So what does that mean, is there a problem only in release build?

The comment by @drescherjm is upvoted which says in release mode the this pointer is not correct because of optimization but what does that exactly mean by 'not correct'? That we can't trust this pointer in release build (is bogus) or that pointer value is correct but release build is broken because of optimizations?

zar
  • 11,361
  • 14
  • 96
  • 178
  • *Inside* the scope of a member function, `this` should never change value. I appears someone may be doing a buffer overrun in `CreateInstance` and `AllocSysString` – StoryTeller - Unslander Monica Aug 23 '16 at 15:51
  • This is most likely to be the bug in your code, where you are using invalid pointer to access the data. Since in your case `this` seems to be on the stack, using pointer incorrectly (i.e. performing out-of-bounds access) modifies it. By the way, what the heck is `m_pCommand`? Some smart (or dumb) pointer? – SergeyA Aug 23 '16 at 15:53
  • 1
    Unless you overwrite its value, which happens here. Look at line 1: m_pCommand = NULL; – unexpectedvalue Aug 23 '16 at 15:53
  • 5
    When you debug it, add a memory write breakpoint on the address `&this`. It should catch the culprit quickly. – StoryTeller - Unslander Monica Aug 23 '16 at 15:54
  • 1
    Chances are, you have a buffer overrun or a dangling pointer somewhere (anywhere) in your program. Use valgrind to find out. – n. m. could be an AI Aug 23 '16 at 15:57
  • Until the definition of m_pCommand is provided, the question is offtopic, and should be closed. – SergeyA Aug 23 '16 at 15:57
  • 5
    Is this a debug build. I mean in release mode the this pointer is not correct because of optimization. – drescherjm Aug 23 '16 at 16:02
  • @SergeyA m_pCommand seems to be COM object of type _CommandPtr and even I can't find its definition in my solution. – zar Aug 23 '16 at 16:07
  • @drescherjm its release build. – zar Aug 23 '16 at 16:07
  • 4
    @zar any debugging done on a program with optimization turned on is going to be providing an approximation of what's happening behind the scenes--after optimization there isn't necessarily going to be a 1:1 mapping of what you wrote to what's getting executed. If it's at all possible to hunt down the problem in debug mode, I generally try that first because of the guessing involved in figuring what's happening in a release build. – jaggedSpire Aug 23 '16 at 16:14
  • Debugging optimized code is *difficult*. You can't really trust the debugger and the code doesn't match the source any more. In such cases I personally find it helpful to look at the generated asm to figure out what's *actually* going on. – Jesper Juhl Aug 23 '16 at 16:43
  • 1
    @jaggedSpire understood particularly for local or member variables but does this has impact on `this` pointer as well? – zar Aug 23 '16 at 16:51

2 Answers2

6

Depending on the debugger, it may be normal to see the value of this change between hitting the function and entering it.

this==0xcccccccc before entering the function

hitting S::f()

this has a valid address after entering the function

entering S::f()

However, once you've entered the function, the value of this shouldn't change1. If it does, it probably means that you have some sort of buffer overrun and are overwriting your stack.

Figuring out the problem can be tricky. You can try putting memory breakpoints on this to see when it changes or commenting out code until the problem disappears. This should help you narrow it down. Note that the culprit might not even be in that particular function: memory corruption is notorious for causing havoc in unrelated places.

You also seem to be looking at this using an optimized build. Be very wary of relying on a debugger when optimizations were used: variables can disappear from your code, giving you the impression that their value is wrong. If you can reproduce the problem, I'd try logging this somewhere instead of looking at it through a debugger. This whole thing might actually be a red herring.

1However, this can change when you're calling another member function across a hierarchy, especially when virtual bases are involved.

isanae
  • 3,253
  • 1
  • 22
  • 47
  • I added update to my question and this issue now is debug vs release build. Understandable that variables may vanish in release build due to optimization but _this_ pointer can't vanish but still its value can't be trusted? And do we just ignore _this_ when let's say if only the release version was crashing? – zar Aug 25 '16 at 15:29
  • @zar The `this` pointer [can absolutely vanish if it's not necessary](https://stackoverflow.com/questions/15718262/what-exactly-is-the-as-if-rule). What you (or the debugger) think is the `this` pointer might actually be used for something else entirely within that function. – isanae Aug 25 '16 at 15:36
  • Thanks and yet this opens a lot more questions. WinDbg is low-level debugger and a lot of operations involving examining this or that memory address, see an object footprint in memory, stack pointer etc and now we know we can't trust pointers in release build which is where we see crash :) – zar Aug 25 '16 at 15:49
  • 1
    @zar It's not that you cannot trust pointers. You cannot trust that there is any sort of relation between your source code and the generated code. Debuggers are useful in unoptimized builds because there is a (mostly) one to one translation from source code to machine code. They can however be very misleading when code has been optimized because they make assumptions that may not be true any more. It's not a problem with codegen, it's a problem with debuggers. – isanae Aug 25 '16 at 16:23
  • 1
    @zar I suggest you ask a new question about the reasons why you cannot easily debug optimized code. There doesn't seem to be any. – isanae Aug 25 '16 at 16:25
0

Since your example starts by creating an instance from a GUID obtained with __uuidof, there is one factor that can also contribute to the release being quite different from the debug code: According to the docs, __uuidof is resoved at runtime in debug builds, and is compiled-in for release builds. For the former, the worst case is that module load/binding order can be affected.

__uuidof Operator

https://msdn.microsoft.com/en-us/library/zaah6a61.aspx


Note:

In a debug build, __uuidof always initializes an object dynamically (at runtime). In a release build, __uuidof can statically (at compile time) initialize an object.

When things go wrong with versioning or otherwise, it's also possible for the runtime value to be different from the static-bound result, meaning you might be debugging different objects in the release vs. debug scenario.

Glenn Slayden
  • 17,543
  • 3
  • 114
  • 108
  • Did you intend to post this answer here? It has nothing to do with the question. – isanae Mar 26 '17 at 22:11
  • @isanae I provided some explanation. If you still think it's irrelevant, let me know and I'll retract. – Glenn Slayden Mar 26 '17 at 23:38
  • Although the example does use `__uuidof`, I don't think it's relevant to the question at all, which was about the value of `this` changing from within the ctor. I don't really care, though. – isanae Mar 26 '17 at 23:42