Over the weekend, one of the developers in my group sent me some mail – he was seeing one of the registers in his code getting corrupted across a procedure call. He was quite surprised to see this, and asked me for any suggestions.
With the help of the info he gave me, I was able to figure out what had gone wrong with his code, and I realized that it’d make a great “what’s wrong with this code” example.
There are three parts to the code associated with this “what’s wrong”. The first is an interface definition:
virtual bool DoSomeOperation(int argc, _TCHAR *argv) = 0;
Next, you have a tiny test application:
int _tmain(int argc, _TCHAR* argv)
register int value1 = 1;
IPsychicInterface *psychicInterface = GetPsychicInterface();
register int value2 = 2;
assert(value1 == 1);
assert(value2 == 2);
The failure happened when the caller returned from psychicInterface->DoSomeOperation – upon the return, the ESI register, which is supposed to be preserved got trashed. Further debugging showed that the reason that ESI was trashed was that the stack was imbalanced after the call to DoSomeOperation.
There’s one more piece of information that I was given that let me immediately realize the root cause of the problem.
I know that if I include that information, what went wrong should be blindingly obvious, so I’m going to be mean and ask you to tell me what the one additional piece of information was. The reason that the other developer in my group didn’t find it was simply because he was looking at too much data – if I had pointed out that one piece of additional data, he’d have instantly figured it out too.
So the “answer” to this part of the “What’s wrong” problem is “What single additional piece of information was I given that made this problem simple to solve?”