Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why aren't #define'd constants known to debugger?

When debugging my code I quite often want to know the value of #define'd constants. But the debugger does not appear to know their values. This means I have to chase around looking at include paths etc to find the #define line. Is there some trick to make this easier?

UPDATE: I had to award the green tick to Tony D for his detailed answer of the headline question, but I have also upvoted the use of const instead of #define (I also tested that enum works too). Finally the use of F12 to find the original #define line was another good idea.

like image 533
Mick Avatar asked Sep 18 '15 10:09

Mick


People also ask

Is aren't grammatically correct?

(“Amn't” is not a word in English.) Therefore, in casual speech and writing, English speakers use aren't, instead, and except in formal situations, this is considered entirely grammatical. I hope this helps.

Why are you not or why aren't you?

'Why are you not . . . ' means exactly the same as 'Why aren't you . . . '. If we spell out 'Why aren't you?' , we get 'why are not you?' , which, in this form, is not idiomatic.

How do I use aren't in a sentence?

1 : are not They aren't here yet. 2 : am not —used in questions I'm right, aren't I?

What is this word aren t?

Aren't is the usual spoken form of 'are not. ' 2. Aren't is the form of 'am not' that is used in questions or tags in spoken English.


2 Answers

For whatever 10 minutes on Google's worth, it seems Visual Studio doesn't support this.

Some compilers do attempt this, but there's a reason it's a bit fragile / best-effort...

To first rehash and knock down the common but bogus explanation for this: there's a conceptually distinct preprocessing step that substitutes text for the uses of preprocessor macros before "proper" compilation begins, but there's really no reason the preprocessing stage can't pass a record of the #define and #undefine statements onwards for inclusion with other debug information.

What is a pain is that what is intuitively and commonly considered "#define-ing a preprocessor constant" isn't anything like...

const Some_Type some_identifier = some_value; 

...in that the latter has a specific location in the application's namespace heirarchy and really can't be changed, while a #define can be #undef-ined and re-#defined any number of times, such that the "value" of a preprocessor macro at a particular line of code can depend on how that line's been included in the translation unit: each inclusion of the same line in each translation unit could have a different value (or no value) for that macro.

For this reason, displaying the "value" of a macro as you're debugging through some code is problematic - it's only guaranteed to have a single value at a particular line in a particular translation unit, but programmers normally want debuggers to show and navigate programs in terms of lines in source files.

Consider:

use_x.h

class T ## X {     void g() { ... } }; 

some_app.cc

#define X 2783 #include "use_x.h" #undef X #define X 2928 #include "use_x.h" void f() {     const int last_x = X; } 

If your debugger's stepping through f() above, X can be said to be 2928, but what if you're stepping through a version of g() - the debugger would have a tough time understanding there's some connection between the class name and the value of X used to create it, or working out what to display some other way....

It gets worse if you hover a mouse over a macro while stopped at some other line - possibly linked in from a different translation unit - it can be impossible for the debugger to know whether you're interested in the last value of that macro that your execution has passed through, or the next value it might have if execution continues (if it can even predict any branching that may happen first), or the value (if any) of the macro at the line the debugger's stopped at.

So, some tool chains (compilers / debug-info-encodings / debuggers) just don't buy into this mess. Better tools might track simple cases then display nothing - or a list of possible values - for cases too complex to analyse. Displaying wrong values is much worse than nothing.


It doesn't help within the debugger, but when macro values/substitutions need to be reviewed you can try cl /E (for GCC/clang the option's -E) to provide preprocessed output for a translation unit - you can then see what substitutions have been made by the preprocessor.

like image 84
Tony Delroy Avatar answered Oct 12 '22 18:10

Tony Delroy


Macros are evaluated and resolved by the preprocessor, before compilation. It's not just that the compiled program doesn't know their values: the compiled program contains no trace of them at all. There's nothing for your debugger to inspect.

Consider macros to be a code generation tool, and everything will become clear.

Some compilers do have a flag you can set to retain the values of various preprocessor definitions and list them in a special area with your executable for debugging purposes. I don't know how to get that to happen in VS, though. I would instead use the relevant switch for only running the preprocessor, then inspect the result.

like image 34
Lightness Races in Orbit Avatar answered Oct 12 '22 16:10

Lightness Races in Orbit