Any way to force local variables to the stack in 64bit VC application
When a 64 bit VC 2005 application is compiled with optimization turned on, it is not possible to see all local variables in a crash dump file. In many cases, the local variables or parameters are stored in registers instead of on the stack. Subsequent calls to other functions, such as error handling functions, will sometimes overwrite those values. This makes it difficult to trace the cause of the problem. Is there a way to force local variables and/or parameters to the s开发者_如何学Ctack at run time?
Turning off the optimization is one way but that makes application slow, and it is generally not a good idea for the release build. I am hoping that there is a run time call that will dump all local variables and/or registry somewhere. If there is such function, we can then call the function before calling the error logging function and will hopefully be able to see more local variable on the stack.
-- Alex
I think you're seeing something else. Most common calling conventions on x86 pass arguments the function arguments on the stack. But the x64 calling convention is different, it is similar to __fastcall on x86, it passes the first 4 function arguments in registers (rcx, rdx, r8 and r9). If the function is non-trivial, the compiler generates code to save those registers on the stack frame right away.
Unfortunately, the debugger isn't smart enough to know about the saved register locations. It displays the register value in the call stack, a value that almost always has changed. You can technically dig the argument value out of the stack frame yourself, but you really, really want to have to do this. In optimized code it is an offset from rsp, not rbp, and the stack pointer value has changed as well.
I haven't found any good workaround for this yet. Looking forward to improvements in the VS2010 debugger, no idea if this was addressed.
If you take the address of a variable, the compiler will be forced to allocate space for it on the stack, so you could write a little macro.
#ifdef DEBUG
#define FORCE_ON_STACK(var) void * p##var##_dummy = (void *)&var
#else
#define FORCE_ON_STACK(var) (void)0 // eat the ;
#endif
The compiler still might be lazy about keeping the value on the stack in sync with the registers in some cases. Also keeping arguments in registers is an important optimization which this will at least partly defeat, so this will impact performance somewhat.
If you upgrade to VC++ 2013 and use the /Zo switch then you will get a much better debugging experience with optimized code, whether 32-bit or 64-bit. This doesn't answer your literal question of how to force variables to the stack, but it does answer your actual question of how to make it easier to see the values of locals and parameters.
Is there a way to force local variables and/or parameters to the stack at run time?
Such a thing is completely impractical; it would require re-compiling the code. John Knoeller's answer is your best bet, otherwise you need to break at each function entry and record the register state.
精彩评论