views:

659

answers:

4

Is it possible for the debugger (or the CLR exception handler) to show the line where the exception happened in Release mode using the pdb?

The code, in release mode, is optimized and do not always follow the order and logic of the "original" code.

It's also surprising that the debugger can navigate through my code step by step, even in Release mode. The optimization should make the navigation very inconfortable.

Could you please clarify those two points for me?

A: 

The debugger makes a best-effort guess at where the problem occurred. It is not guaranteed to be 100% accurate, and with fully optimized code, it often will be inaccurate - I've found the inaccuracies ranging anywhere from a few lines off to having an entirely wrong call stack.

How accurate the debugger is with optimized code really depends on the code itself and which optimizations you're making.

Not Sure
Ty."to having an entirely wrong call stack."the stack trace should'nt always be acurate?
+1  A: 

I'm not as familiar with how this is done with CLR, but it's probably very similar to how it's done with native code. When the compiler generates machine instructions, it adds entries to the pdb that basically say "the instruction at the current address, X, came from line 25 in foo.cpp".

The debugger knows what program address is currently executing. So it looks up some address, X, in the pdb and sees that it came from line 25 in foo.cpp. Using this, it's able to "step" through your source code.

This process is the same regardless of Debug or Release mode (provided that a pdb is generated at all in Release mode). You are right, however, that often in release mode due to optimizations the debugger won't step "linearly" through the code. It might jump around to different lines unexpectedly. This is due to the optimizer changing the order of instructions, but it doesn't change the address-to-source-line mapping, so the debugger is still able to follow it.

Dan Moulding
Ty for your detailed answer. Things are clear now for me.
A: 

Reference the following SO question:

Display lines number in stack trace for .NET assembly in release mode

Michael Kniskern
A: 

[@Not Sure] has it almost right. The compiler makes a best effort at identifying an appropriate line number that closely matches the current machine code instruction.

The PDB and the debugger don't know anything about optimizations; the PDB file essentially maps address locations in the machine code to source code line numbers. In optimized code, it's not always possible to match exactly an assembly instruction to a specific line of source code, so the compiler will write to the PDB the closest thing it has at hand. This might be "the source code line before", or "the source code line of the enclosing context (loop, etc)" or something else.

Regardless, the debugger essentially finds the entry in the PDB map closest (as in "before or equal") to the current IP (Instruction Pointer) and highlights that line.

Sometimes the match is not very good, and that's when you see the highlighted area jumping all over the place.

Euro Micelli
Maybe the compiler generate a different pdb for release and for debug mode. The pdb for release mode take in consideration optimisation, so it can give a relatively accurate line for an exception.
Oh, absolutely. The PDB is forever tied to the same exact instance of the DLL (or EXE) with which it was built. Note that even if you recompile in the same mode, without any source file changes, you still can't mix and match the PDBs and DLLs. Your PDB must be the same exact one that was created when the module (DLL or EXE) that you are debugging was compiled because the compiler might randomly put stuff in different places on each build. Was that what you were trying to do?
Euro Micelli
@Euro Micelli: > the compiler might randomly put stuff in different places on each build < That sounds to me like a recipe for disaster. I've never seen such a thing in practice. It this something that only happens using Microsoft tools? Or .NET? In every instance that I've had experience with, the compiler will always generate the exact same bit-for-bit result from a given input. Anything else would be highly suspect (can you say "unreproducible build"??)
Dan Moulding
@Dan Moulding: I don't agree. I'm not aware of any standard that requires a compiler output to be 100% identical every time. Compilers are [?] only required to output a 'valid' implementation. The MS linker will definitely apply different metadata on the DLL on every build (like the build Timestamp). In my early years I had a piece of C++ code that had a hidden dependency on the order of static initialization; it worked only once every other compile or so. Unmatched PDBs might work 'mostly', but I've definitely seen cases where an unmatched PDB causes bewildering behavior in the debugger.
Euro Micelli

related questions