[optional] Making optional more debugger friendly

My only complaint about boost::optional is that it is very difficult to see values in the debugger. I brought this up in a discussion at BoostCon, and Jeff Garland suggested I submit a patch. Well, I have a patch. The change introduces a new private T* m_value and protected method update_debug() which sets this variable. The variable is only visible when building debug, and the method is empty in non-debug. From there, I simply call update_debug() in each public method that changes the storage. The final result is that debuggers can see the variable data by looking at opt.m_value. When not set, the value is null. Any thoughts? Jeff Faust

On 5/22/07, Jeffrey Faust <jefffaust@verizon.net> wrote:
My only complaint about boost::optional is that it is very difficult to see values in the debugger. I brought this up in a discussion at BoostCon, and Jeff Garland suggested I submit a patch.
Well, I have a patch. The change introduces a new private T* m_value and protected method update_debug() which sets this variable. The variable is only visible when building debug, and the method is empty in non-debug. From there, I simply call update_debug() in each public method that changes the storage.
The final result is that debuggers can see the variable data by looking at opt.m_value. When not set, the value is null.
Any thoughts?
This means that optional becomes bigger when debugging is enabled, right? Also, is debugging enabled when NDEBUG is not defined, right (it seems so looking at the patch)? I think that this functionality would be useful (even if I haven't needed it yet), but I think it should be enabled by another specific debug directive and shouldn't depend from NDEBUG. I think that many programmers leave NDEBUG undefined even on release builds, because it usually has little or no effect to performance that much. In this case a debug build it would not only be (marginally) slower, but will also take more memory. If you use for example big arrays of optionals it would be noticeable. But more importantly it would make a binary or library compiled with NDEBUG incompatible with one compiled without. While it is technically undefined behavior because it would lead to ODR violation, nevertheless, this is often done and on most systems it simply works. The best thing would probably be to use a different, optional specific, macro. If you really want to use NDEBUG, you could reuse the storage of the bool. Replace it with the pointer and use the pointer to store the "initialized/not initialized" state. This might still be wasteful on 64 bits architectures, but it is better than nothing. gpd

On Tue, 22 May 2007 13:38:18 -0700, Giovanni Piero Deretta <gpderetta@gmail.com> wrote:
This means that optional becomes bigger when debugging is enabled, right? Also, is debugging enabled when NDEBUG is not defined, right (it seems so looking at the patch)?
That's correct.
I think that this functionality would be useful (even if I haven't needed it yet), but I think it should be enabled by another specific debug directive and shouldn't depend from NDEBUG. I think that many programmers leave NDEBUG undefined even on release builds, because it usually has little or no effect to performance that much.
Fair enough. How about BOOST_OPTIONAL_DEBUG?
In this case a debug build it would not only be (marginally) slower, but will also take more memory. If you use for example big arrays of optionals it would be noticeable.
I'm not too concerned about this...
But more importantly it would make a binary or library compiled with NDEBUG incompatible with one compiled without. While it is technically undefined behavior because it would lead to ODR violation, nevertheless, this is often done and on most systems it simply works.
... but this is a very good point! I don't want to break something that currently works, even if it only works by accident.
The best thing would probably be to use a different, optional specific, macro. If you really want to use NDEBUG, you could reuse the storage of the bool. Replace it with the pointer and use the pointer to store the "initialized/not initialized" state. This might still be wasteful on 64 bits architectures, but it is better than nothing.
Reusing the bool is an interesting idea, but I'm happy to use a different precompiler macro. It does lead me to another question. An introduction of a new macro will also require a change to the documentation. I know how to submit a code patch, but how do you submit a doc patch? Jeff Faust

Jeffrey Faust a écrit :
My only complaint about boost::optional is that it is very difficult to see values in the debugger.
variant probably has the same problem. I don't see why you would need to look at its content in the debugger anyway, it's a pretty safe tool.
Well, I have a patch. The change introduces a new private T* m_value and protected method update_debug() which sets this variable.
I think you should just provide an alternative implementation that uses heap allocation instead of stack allocation.

Mathias Gaunard wrote:
Jeffrey Faust a écrit :
My only complaint about boost::optional is that it is very difficult to see values in the debugger.
variant probably has the same problem. I don't see why you would need to look at its content in the debugger anyway, it's a pretty safe tool.
For the same reason I'd like to see values of ints or doubles. It's not because I don't trust boost::optional, but because I simply want to see the value.
Well, I have a patch. The change introduces a new private T* m_value and protected method update_debug() which sets this variable.
I think you should just provide an alternative implementation that uses heap allocation instead of stack allocation.
I'm not sure I follow. Where would this alternative implementation go? Wouldn't this kill performance? Jeff

Mathias Gaunard wrote:
But about performance anyway, doesn't enabling debug mode on your compiler already kill performance?
Tremendously, up to 10x with our checked STL implementation. But it has its uses. We have a large commercial package. In house, we use both debug and non-debug builds for regular work. We only release non-debug builds to our customers. I'm sure this is typical. Jeff

Mathias Gaunard wrote:
Jeffrey Faust wrote:
For the same reason I'd like to see values of ints or doubles. It's not because I don't trust boost::optional, but because I simply want to see the value.
In that case, isn't what needs to be improved your debugger rather than boost::optional?
By the time the value has been stored in boost::optional, it has been stripped of all type information (as far as I can see). VS8 is actually pretty good at looking at values, and is the best debugger I've seen, although my experience it admittedly limited. I don't know if I'd expect a debugger to make sense of the aligned_memory construct used in boost::optional. Jeff Faust

Jeffrey Faust wrote:
My only complaint about boost::optional is that it is very difficult to see values in the debugger. I brought this up in a discussion at BoostCon, and Jeff Garland suggested I submit a patch.
Well, I have a patch. The change introduces a new private T* m_value and protected method update_debug() which sets this variable. The variable is only visible when building debug, and the method is empty in non-debug. From there, I simply call update_debug() in each public method that changes the storage.
The final result is that debuggers can see the variable data by looking at opt.m_value. When not set, the value is null.
Any thoughts?
If I want to see the result of an optional, I often write code that looks like the following: optional<int> opt; /// Time passes... if (opt) { const int &i = *opt; Then I can just watch i. I do the same thing with iterators, especially into sets and maps. Joe Gottman

Joe Gottman wrote:
If I want to see the result of an optional, I often write code that looks like the following:
optional<int> opt; /// Time passes... if (opt) { const int &i = *opt;
Then I can just watch i. I do the same thing with iterators, especially into sets and maps.
Joe Gottman
That's a technique I use, but it's intrusive. I use boost::optional like a value type. I'd like it to be as transparent to the debugger as the type it wraps. My coworkers have also expressed this issue when I started using boost::optional in our code. Is there anybody out there besides me that would find this useful? If not, I'm happy to drop it. I can always implement it locally for our own use. Jeff

On 5/22/07, Jeffrey Faust <jefffaust@verizon.net> wrote:
That's a technique I use, but it's intrusive. I use boost::optional like a value type. I'd like it to be as transparent to the debugger as the type it wraps. My coworkers have also expressed this issue when I started using boost::optional in our code.
Is there anybody out there besides me that would find this useful? If not, I'm happy to drop it. I can always implement it locally for our own use.
I'm interested in non-intrusive means, of which neither of your proposals really satisfy. Modifying your own code to store the value and watching that variable in the debugger is just a workaround for the debugger's deficiency. I think all of the previous points raised by Giovanni about modifying the Boost code and imposing yet another macro are valid, and it is a better but still undesirable solution. There have been a few threads specific to debugging Boost libraries in Visual Studio (3 to be exact, links below) which would be of interest to me if implemented on a larger and more complete scale. Modifying autoexp.dat to allow Boost classes to be visualized is non-intrusive and ideal IMHO, although, one could still argue it's just a workaround for a deficient debugger ;) Here are the thread references: http://thread.gmane.org/gmane.comp.lib.boost.user/26536 http://thread.gmane.org/gmane.comp.lib.boost.user/18665/focus=18684 http://thread.gmane.org/gmane.comp.lib.boost.user/20464/focus=20483 Are there non-intrusive solutions like the above for other debuggers? I realize it's yet another bit of maintenance, but being able to properly visualize all of Boost in all or most popular debuggers would be very cool. --Michael Fawcett

Michael Fawcett wrote:
On 5/22/07, Jeffrey Faust <jefffaust@verizon.net> wrote:
I'm interested in non-intrusive means, of which neither of your proposals really satisfy. Modifying your own code to store the value and watching that variable in the debugger is just a workaround for the debugger's deficiency. I think all of the previous points raised by Giovanni about modifying the Boost code and imposing yet another macro are valid, and it is a better but still undesirable solution.
I suppose you could argue that a debugger should be able to look at any address as any type you pick. The aligned memory construct is certainly a difficult case. True, it is an intrusive patch, but that's not what I meant. An intrusive change into library code is not noticed by the user. My goal was to provide a benefit to what I see is a weakness in the library, at very little cost.
There have been a few threads specific to debugging Boost libraries in Visual Studio (3 to be exact, links below) which would be of interest to me if implemented on a larger and more complete scale. Modifying autoexp.dat to allow Boost classes to be visualized is non-intrusive and ideal IMHO, although, one could still argue it's just a workaround for a deficient debugger ;)
Thanks for the links. I'll definitely use the ptr container additions. Still, I've tried to find a solution for boost::optional some time ago and failed. The link that mentions it is for only int64, and not a general solution. I'll try to tackle the problem again with autoexp.dat. However, I've failed previously, and don't expect better results this time around. Jeff Faust

Jeffrey Faust wrote:
Thanks for the links. I'll definitely use the ptr container additions. Still, I've tried to find a solution for boost::optional some time ago and failed. The link that mentions it is for only int64, and not a general solution. I'll try to tackle the problem again with autoexp.dat. However, I've failed previously, and don't expect better results this time around.
Hi Jeff, We have a handful of VS2005 visualizers for boost types. Here's what we use for boost::optional. Try plugging this into the [Visualizers] section of your autoexp.dat and see if it is the kind of thing you are looking for: boost::optional<*>{ preview ( #if( !$c.m_initialized ) ( #( "Uninitialized" ) ) #else ( #( *($T1*)&$c.m_storage.dummy_.data[0] ) ) ) } I am using VS2005 SP1 in case it makes a difference (I can't remember if SP1 altered the debug visualizer stuff or not). -Dave boost::optional<*>{ preview ( #if( !$c.m_initialized ) ( #( "Uninitialized" ) ) #else ( #( *($T1*)&$c.m_storage.dummy_.data[0] ) ) ) }

David Deakins wrote:
Hi Jeff,
We have a handful of VS2005 visualizers for boost types. Here's what we use for boost::optional. Try plugging this into the [Visualizers] section of your autoexp.dat and see if it is the kind of thing you are looking for:
boost::optional<*>{ preview ( #if( !$c.m_initialized ) ( #( "Uninitialized" ) ) #else ( #( *($T1*)&$c.m_storage.dummy_.data[0] ) ) ) }
Dave, you have made my day. This is exactly what I need. It works perfectly! Now, how do people feel about an update to the documentation with this debugger-specific nugget? Do other debuggers have similar facilities? Jeff

Jeffrey Faust wrote:
David Deakins wrote:
Hi Jeff,
We have a handful of VS2005 visualizers for boost types. Here's what we use for boost::optional. Try plugging this into the [Visualizers] ...snip.... Dave, you have made my day. This is exactly what I need. It works perfectly!
Now, how do people feel about an update to the documentation with this debugger-specific nugget? Do other debuggers have similar facilities?
So perhaps these sort of debugger add-ins could be added under 'tools/debug'. If someone could write up an html page that describes them we could simply add a link from the current boost.tools page. Since some of them are ultimately library specific, it might be nice if the library docs would add a link back to these. Does that make sense? Do we have a volunteer(s)? Jeff

Jeffrey Faust wrote:
Is there anybody out there besides me that would find this useful?
I can't speek to the solution itself but I would find it very useful. It's a productivity issue. In the end the gains of using optional have to be weighed against its drawbacks. Lack of inspectability is a big minus. It goes so far that it limits adoption here. With respect to this being rather a debugger problem: I've entertained that thought for a moment but then I realized I can't stop writing code while the debugger is getting fixed. In practice it's a library issue. Thomas -- Thomas Witt witt@acm.org

Hi Thomas, Thomas Witt wrote:
Jeffrey Faust wrote:
Is there anybody out there besides me that would find this useful?
I can't speek to the solution itself but I would find it very useful. It's a productivity issue. In the end the gains of using optional have to be weighed against its drawbacks. Lack of inspectability is a big minus. It goes so far that it limits adoption here.
I'm glad I'm not alone.
With respect to this being rather a debugger problem: I've entertained that thought for a moment but then I realized I can't stop writing code while the debugger is getting fixed. In practice it's a library issue.
With all the feedback I've gotten, I want to abandon my proposed approach and try something else. Most importantly, the debugger version has to be a different type to avoid debug/release compatability issues. Jeff Faust

Hi Jeffrey, In my experience, changing the class layout based on a preprocessor switch is a very bad idea since it breaks binary compatibility with libraries compiled with a different switch, so I strongly suggest you/we find a better solution. If this functionality is really really needed (read below), I would create a *different* template class to offer it. One such debugger-friendly optional<> would replace (rather than add) the bool field with a T* field (which would be set to NULL when uninitialized). A different template class makes sure that binary-differing optional's don't mix accidentally (in the same wa a policy-based design does it). But I'm curious: doesn't a simple dynamic watch, like "*opt", works?? That calls a method on the object, yes, but debuggers have been able to do that for decades now. Or perhaps your problem is that you don't want to be watching/inspecting "*opt" manually? I'm using C# a lot lately and it has a nice feature: the debugger automatically calls .ToString() on any variable it shows. That's *so* useful. Doesn't VC++ has some sort of similar mechanism? Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com

Fernando Cacciola wrote:
Hi Jeffrey,
In my experience, changing the class layout based on a preprocessor switch is a very bad idea since it breaks binary compatibility with libraries compiled with a different switch, so I strongly suggest you/we find a better solution.
I agree. This is probably the largest drawback. I'll look further.
If this functionality is really really needed (read below), I would create a *different* template class to offer it. One such debugger-friendly optional<> would replace (rather than add) the bool field with a T* field (which would be set to NULL when uninitialized). A different template class makes sure that binary-differing optional's don't mix accidentally (in the same wa a policy-based design does it).
I'll see what I can do with this. Perhaps this other class will wrap the real boost::optional, providing the same interface, and giving an additional debug value. This would make it easier to keep the two classes in sync.
But I'm curious: doesn't a simple dynamic watch, like "*opt", works?? That calls a method on the object, yes, but debuggers have been able to do that for decades now.
Quite honestly, I couldn't answer this before I tried it. Using the "Immediate Window" in VC8 gives the error "CXX0034: Error: types incompatible with operator." Now this is a legitimate debugger problem. Thanks for the idea, Jeff Faust

Jeffrey Faust wrote:
Quite honestly, I couldn't answer this before I tried it. Using the "Immediate Window" in VC8 gives the error "CXX0034: Error: types incompatible with operator." Now this is a legitimate debugger problem.
Does it work if you call a method like ".value()"? (which optional<> doesn't has but which *can* be added within a compiler switch as it doesn't affect the object layout). -- Fernando Cacciola SciSoft http://fcacciola.50webs.com

Fernando Cacciola wrote:
Does it work if you call a method like ".value()"? (which optional<> doesn't has but which *can* be added within a compiler switch as it doesn't affect the object layout).
os.get() CXX0039: Error: symbol is ambiguous os.get_ptr() CXX0039: Error: symbol is ambiguous os.is_initialized() true os.get_impl() CXX0039: Error: symbol is ambiguous os.m_value (my proposal) "Hello, World!" This is unfortunate. Jeff Faust

On Tuesday 22 May 2007 21:19:11 Jeffrey Faust wrote:
My only complaint about boost::optional is that it is very difficult to see values in the debugger. I brought this up in a discussion at BoostCon, and Jeff Garland suggested I submit a patch.
Well, I have a patch. The change introduces a new private T* m_value and protected method update_debug() which sets this variable. The variable is only visible when building debug, and the method is empty in non-debug. From there, I simply call update_debug() in each public method that changes the storage.
The final result is that debuggers can see the variable data by looking at opt.m_value. When not set, the value is null.
I'm not against making things debugger-friendly, but not at the cost of performance. Also, I find the objections about having different layouts valid. Other than that, I know that at least GDB and MS debugger can be scripted and that it might be a different approach that is non-intrusive. Uli

Ulrich Eckhardt skrev:
I'm not against making things debugger-friendly, but not at the cost of performance. Also, I find the objections about having different layouts valid.
Other than that, I know that at least GDB and MS debugger can be scripted and that it might be a different approach that is non-intrusive.
I think this is the way to go. We should somehow have a standard repository for these scripts ... they are useful for a number of other libraries that are hard to debug, eg. boost.ptr_container, boost.variant, boost.any etc -Thorsten

Ulrich Eckhardt wrote:
I'm not against making things debugger-friendly, but not at the cost of performance. Also, I find the objections about having different layouts valid.
It would only be for a "debug" build--where the extra information would be usable, and where the user has made some explicit choice that performance is not as important as extra information. That's the idea behind a checked STL implementation, which will assert if it detects something invalid. The issue of different layouts is a problem. I had not considered that. Now that it's been brought up 3 times, I'm thouroughly aware of it ;)
Other than that, I know that at least GDB and MS debugger can be scripted and that it might be a different approach that is non-intrusive.
I have tried to modify autoexp.dat in the past, but have failed. I'll give it another try before looking for another solution. Thanks for the feedback, Jeff Faust

"Jeffrey Faust" <jefffaust@verizon.net> wrote in message news:op.tsr4k6sq5emtmi@goliath...
Ulrich Eckhardt wrote:
Other than that, I know that at least GDB and MS debugger can be scripted and that it might be a different approach that is non-intrusive.
I have tried to modify autoexp.dat in the past, but have failed. I'll give it another try before looking for another solution.
Jeff, Since you are using the Visual Studio products there is an option might get you where you want to be w/out requiring *any* intrusive modification in your code (or to boost). It is possible to write custom 'Add-in' DLLs to help the debugger display values in the IDE. I'm attaching a sample that I pieced together from a couple different posts. Much of the code comes from Jason Shirk in response to a problem displaying std::string in the debugger correctly (search for "autoexp.dat is wrong for std:basic_string"). I had to make some changes and piece some information together from a few other sources as well but I got the example file working. At the bottom of the file you'll find some comments from the author(s), a link to the threads that discuss the problem, and some of my own comments based on actually trying to use it and see how it works. With a little elbow grease you should be able to put together one for your use with boost::optional. HTH, -Chris begin 666 EEStdString.cpp M+R\@17AP<F5S<VEO;B!%=F%L=6%T;W(@061D+4EN(&9O<B!T:&4@5FES=6%L M($,K*R!D96)U9V=E<BX*+R\*+R\@5&AI<R!S;VQV97,@=&AE('!R;V)L96T@ M=&AA="!T:&4@5FES=6%L(%-T=61I;R N3D54(&1E8G5G9V5R(&1O97,@;F]T M('!R;W!E<FQY"B\O(&1I<W!L87D@<W1D.CIS=')I;F<@97AP<F5S<VEO;G,@ M=VAE;B!T:&4@<W1R:6YG(&AA<R!M;W)E('1H86X@,34@8VAA<F%C=&5R<RX* M+R\@1V%R8F%G92!I<R!D:7-P;&%Y960@9F]R(&QO;F=E<B!S=')I;F=S+B @ M*$5X<&%N9&EN9R!T:&4@<W1R=6-T=7)E('=O<FMS"B\O(&-O<G)E8W1L>2!I M;B!A;&P@8V%S97,N*0HO+PHO+R!4:&ES(&-O9&4@:&%S(&)E96X@=&5S=&5D M('=I=&@@,S(M8FET(%9I<W5A;"!3='5D:6\@+DY%5#L@:70@:7,@86QS;R!B M96QI979E9"!T;PHO+R!W;W)K('=I=&@@-C0M8FET(&%N9"!W:71H(%9I<W5A M;"!3='5D:6\@-BP@86QT:&]U9V@@;F5I=&AE<B!H87,@8F5E;B!T97-T960N M("!4:&ES"B\O(&-O9&4@:&%N9&QE<R!!4T-)22!S=')I;F=S.R!5;FEC;V1E M('-T<FEN9W,@87)E(&QE9G0@87,@86X@97AE<F-I<V4@9F]R('1H92!R96%D M97(N"B\O"B\O($9O<B!M;W)E(&1E=&%I;',L(&EN8VQU9&EN9R!C<F5D:71S M(&%N9"!H;W<@=&\@8G5I;&0O:6YS=&%L;"!T:&ES(&%D9"UI;BP@<V5E('1H M90HO+R!C;VUM96YT<R!A="!T:&4@8F]T=&]M(&]F('1H:7,@9FEL92X*"B-I M;F-L=61E(#QW:6YD;W=S+F@^"B-I;F-L=61E(#QS=')I;F<^"B-I;F-L=61E M(#QM86QL;V,N:#X*(VEN8VQU9&4@/'-T9&EO+F@^"@H*+R\@5&AE(&-A;&QB M86-K('!O:6YT97(@=V4@87)E('!A<W-E9"!R969E<G,@=&\@;VYE(&]F('1H M97-E"G1Y<&5D968@<W1R=6-T('1A9T1%0E5'2$5,4$52"GL*"4173U)$(&1W M5F5R<VEO;CL*"4)/3TP@*%=)3D%022 J4F5A9$1E8G5G9V5E365M;W)Y*2@@ M<W1R=6-T('1A9T1%0E5'2$5,4$52("IP5&AI<RP@1%=/4D0@9'=!9&1R+"!$ M5T]21"!N5V%N="P@5D])1"H@<%=H97)E+"!$5T]21" J;D=O=" I.PH)+R\@ M9G)O;2!H97)E(&]N(&]N;'D@=VAE;B!D=U9E<G-I;VX@/CT@,'@R,# P," H M+DY%5"!O<B!L871E<BD*"4173U)$3$].1R H5TE.05!)("I'971296%L061D M<F5S<RDH('-T<G5C="!T86=$14)51TA%3%!%4B J<%1H:7,@*3L*"4)/3TP@ M*%=)3D%022 J4F5A9$1E8G5G9V5E365M;W)Y17@I*"!S=')U8W0@=&%G1$5" M54=(14Q015(@*G!4:&ES+"!$5T]21$Q/3D<@<7=!9&1R+"!$5T]21"!N5V%N M="P@5D])1"H@<%=H97)E+"!$5T]21" J;D=O=" I.PH):6YT("A724Y!4$D@ M*D=E=%!R;V-E<W-O<E1Y<&4I*"!S=')U8W0@=&%G1$5"54=(14Q015(@*G!4 M:&ES("D["GT@1$5"54=(14Q015(["@H*+R\@2&5L<&5R(&9U;F-T:6]N+"!S M:6YC92!W92!R96%D(&9R;VT@<V5V97)A;"!P;&%C97,N("!$;V5S(&-O;6UO M;B!E<G)O<B!C:&5C:VEN9RX*=F]I9"!'971287=">71E<RA$14)51TA%3%!% M4B J<$AE;'!E<BP@=F]I9"H@861D<F5S<RP@=F]I9" J<$1S="P@<VEZ95]T M('-I>F5/9D1S="D*>PH@(" @1%=/4D0@;E)E860["B @("!(4D5354Q4(&AR M.PH*(" @(&EF("AP2&5L<&5R+3YD=U9E<G-I;VX@/" P>#(P,# P('Q\('-I M>F5O9BAV;VED*BD@/3T@<VEZ96]F*$173U)$*2D@>PH)"2\O(%9I<W5A;"!# M*RL@-BXP('9E<G-I;VXN(" P>&,G<R ]/2!U;FEN:71I86QI>F5D('-T86-K M"@D):68@*"AA9&1R97-S/3TP*2!\?" H861D<F5S<R ]/2 H=F]I9"HI,'AC M8V-C8V-C8RDI<F5T=7)N.PH@(" @(" @(&AR(#T@<$AE;'!E<BT^4F5A9$1E M8G5G9V5E365M;W)Y*'!(96QP97(L("A$5T]21"EA9&1R97-S+"!S:7IE3V9$ M<W0L('!$<W0L("9N4F5A9"D["@H@(" @?2!E;'-E('L*"0DO+R!6:7-U86P@ M0RLK("Y.150@=F5R<VEO;BX@(#!X8R=S(#T]('5N:6YI=&EA;&EZ960@<W1A M8VL*"0EI9B H*&%D9')E<W,]/3 I('Q\("AA9&1R97-S(#T]("AV;VED*BDP M>&-C8V-C8V-C8V-C8V-C8V,I*2!R971U<FX["B @(" @(" @:'(@/2!P2&5L M<&5R+3Y296%D1&5B=6=G965-96UO<GE%>"AP2&5L<&5R+" H1%=/4D1,3TY' M*6%D9')E<W,L('-I>F5/9D1S="P@<$1S="P@)FY296%D*3L*(" @('T*"@DO M+R!#;VUM;VX@97)R;W(@8VAE8VMI;F<*(" @(&EF("AH<B A/2!37T]+*2![ M"B @(" @(" @4F%I<V5%>&-E<'1I;VXH4U1!5%537T%#0T534U]624],051) M3TXL(# L(# L(# I.PH@(" @(" @(')E='5R;CL*(" @('T*"B @("!I9B H M;E)E860@(3T@<VEZ94]F1'-T*2!["B @(" @(" @4F%I<V5%>&-E<'1I;VXH M4U1!5%537T%#0T534U]624],051)3TXL(# L(# L(# I.PH@(" @(" @(')E M='5R;CL*(" @('T*?0H*+R\@1G5N8W1I;VX@=&AA="!I<R!C86QL960@*&)Y M('1H92!D96)U9V=E<BD@=&\@979A;'5A=&4@=&AE('-T<FEN9PIE>'1E<FX@ M(D,B"DA215-53%0@7U]D96-L<W!E8RAD;&QE>'!O<G0I(%=)3D%022!!=71O M17AP4W1D4W1R:6YG* H)1%=/4D0@9'=!9&1R97-S+ D)"2\O(&QO=R S,BUB M:71S(&]F('1H92!D96)U9V=E92!A9&1R97-S(&]F('1H92!S=')I;F<*"41% M0E5'2$5,4$52("IP2&5L<&5R+ D)+R\@8V%L;&)A8VL@<&]I;G1E<B!T;R!A M8V-E<W,@:&5L<&5R(&9U;F-T:6]N<PH):6YT(&Y"87-E+ D)"0D)+R\@9&5C M:6UA;"!O<B!H97@*"4)/3TP@8E5N:5-T<FEN9W,L"0D)+R\@<W1R:6YG(&ES M(%5N:6-O9&4@*"!O;FQI;F4@9&]C('-A>7,@;F]T('5S960@*0H)8VAA<B J M<%)E<W5L="P)"0D)+R\@=VAE<F4@=&AE(')E<W5L="!N965D<R!T;R!G;PH) M<VEZ95]T(&UA>"P)"0D)"2\O(&AO=R!L87)G92!T:&4@86)O=F4@8G5F9F5R M(&ES"@E$5T]21"!D=U)E<V5R=F5D*0D)"2\O(&%L=V%Y<R!P87-S('IE<F\* M>PH)*G!297-U;'0@/2 G7# G.PD)"2\O($YE961S('1O(&)E(&1O;F4L(&5V M96X@:68@=V4@9V5T(&%N(&5X8V5P=&EO;@H)7U]T<GD@>PH)"2\O(%=E(&1O M;B=T(&YE960@=&\@8V]N<W1R=6-T(&$@;&]C86P@<W1R:6YG+"!B=70@=V4@ M;F5E9"!M96UO<GD@=&\@:&]L9"!O;F4N"@D)+R\@06QS;RP@:68@=V4@:&%D M(&$@;&]C86P@;V)J96-T+"!W92!C;W5L9&XG="!U<V4@4T5(("A314@@86YD M($,K*R!D;VXG="!M:7@I+@H)"6-H87(@<W1R8G5F(%L@<VEZ96]F*'-T9#HZ M<W1R:6YG*2!=.PH)"7-T9#HZ<W1R:6YG("IS='(@/2 H<W1D.CIS=')I;F<J M*7-T<F)U9CL*"@D)+R\@1V5T('1H92!C;W)E8W0@861D<F5S<R M+2!E:71H M97(@,S(M8FET(&]R(#8T+6)I= H)"4173U)$3$].1R!R96%L061D<F5S<R ] M"@D)"2@H<$AE;'!E<BT^9'=697)S:6]N(#P@,'@R,# P,"D@?'P@*'-I>F5O M9BA$5T]21$Q/3D<I(#T]('-I>F5O9BA$5T]21"DI*0H)"0D)/R!D=T%D9')E M<W,)"0D)"0D)+R\@5D,K*R V+C L(#,R+6)I="!A9&1R97-S(&]N;'D*"0D) M"3H@<$AE;'!E<BT^1V5T4F5A;$%D9')E<W,H<$AE;'!E<BD["2\O(%9#*RL@ M+DY%5"P@-C0M8FET(&%D9')E<W,*"@D)+R\@0V]P>2!T:&4@<W1R:6YG(&]B M:F5C="!I='-E;&8@9G)O;2!T:&4@9&5B=6=G964@:6YT;R!O=7(@861D<F5S M<R!S<&%C92X*"0E'971287=">71E<RAP2&5L<&5R+" H=F]I9"HI<F5A;$%D M9')E<W,L('-T<BP@<VEZ96]F*'-T9#HZ<W1R:6YG*2D["@H)"2\O(%1H:7,@ M<F5L:65S(&]N(&MN;W=L961G92!O9B!I;G1E<FYA;"!I;7!L96UE;G1A=&EO M;B!D971A:6QS+@H)"6-O;G-T(&-H87(J(&-?<W1R(#T@<W1R+3YC7W-T<B@I M.PH)"6EF("AC7W-T<B F)B!M87@^,2D*"0E["@D)"7-T9#HZ<W1R:6YG.CIS M:7IE7W1Y<&4@;&5N9W1H(#T@;6EN*'-T<BT^;&5N9W1H*"DL(&UA>"TR*3L* M"@D)"7!297-U;'1;,%T@/2 G(B<["@H)"0EI9B H<W1D.CIS=')I;F<Z.E]" M549?4TE:12 \/2!S='(M/F-A<&%C:71Y*"D@)B8@;&5N9W1H*0H)"0E["@D) M"0DO+R!,87)G92!S=')I;F<L(&-?<W1R("T^(&1E8G5G9V5E)W,@861D<F5S M<R!S<&%C90H)"0D)+R\@0V]P>2!T:&4@86-T=6%L('-T<FEN9R!D871A"@D) M"0E'971287=">71E<RAP2&5L<&5R+" H=F]I9"HI8U]S='(L('!297-U;'0K M,2P@;&5N9W1H*3L*"0D)?0H)"0EE;'-E(&EF("AL96YG=&@I"@D)"7L*"0D) M"2\O(%-M86QL('-T<FEN9RP@8U]S='(@+3X@;W5R(&%D9')E<W,@<W!A8V4@ M*&-O<&EE9"!I;B!A8F]V92D*"0D)"5]S;G!R:6YT9BAP4F5S=6QT*S$L(&QE M;F=T:"P@(B5S(BP@8U]S='(I.PH)"0E]"@H)"0EP4F5S=6QT6VQE;F=T:"LQ M72 ]("<B)SL*"0E]"@E](%]?97AC97!T("@@15A#15!424].7T5814-55$5? M2$%.1$Q%4B I('L*"0D@(')E='5R;B!%7T9!24P["@E]"@H)<F5T=7)N(%-? M3TL["GT*"B\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O M+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\*+R\) M"0D)"0D)"0D)"0D)"0D)"0D)("\O"B\O(" @("!!;&P@8F5L;W<@:&5R92!I M<R!G96YE<F%L(&-O;6UE;G1S+B @5&AE<F4@:7,@;F\@8V]D92!B96QO=R!H M97)E+B @(" @+R\*+R\)"0D)"0D)"0D)"0D)"0D)"0D)("\O"B\O+R\O+R\O M+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O M+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\O+R\*"B\O(%1H:7,@861D+6EN('-O M;'9E<R!T:&4@<')O8FQE;2!T:&%T('1H92!D96)U9V=E<B!D;V5S(&YO="!P M<F]P97)L>2!D:7-P;&%Y"B\O('-T9#HZ<W1R:6YG('=H96X@=&AE('-T<FEN M9R!H87,@;6]R92!T:&%N(#$U(&-H87)A8W1E<G,N("!%>'!A;F1I;F<@=&AE M"B\O('-T<FEN9R!D:7-P;&%Y<R!T:&4@8V]R<F5C="!I;F9O<FUA=&EO;B!I M;B!A;&P@8V%S97,L(&)U="!W:&%T(&ES('-H;W=N(&EN('1H90HO+R!U;F5X M<&%N9&5D('9I97<@:7,@;F]T(&-O<G)E8W0@9F]R(&QO;F=E<B!S=')I;F=S M("TM(&ET(&ES(')A;F1O;2!G87)B86=E+@H*+R\@5&AE('5N9&5R;'EI;F<@ M<')O8FQE;2!I<R!T:&%T($UI8W)O<V]F="!S=')I;F<@;V)J96-T(&ME97!S M(")S:&]R="(@<W1R:6YG<PHO+R H=7 @=&\@,34@8VAA<F%C=&5R<RD@<FEG M:'0@:6X@=&AE(&]B:F5C=#L@(&9O<B!L;VYG97(@<W1R:6YG<R!I="!K965P M<R!A"B\O('!O:6YT97(N("!/;FQY(&]N92!O9B!T:&5M(&ES('9A;&ED(&9O M<B!A;GD@9VEV96X@<W1R:6YG+B @5&AE(&1E8G5G9V5R"B\O("AA8W1U86QL M>2P@=&AE('-H:7!P960@875T;V5X<"YD870I(&]N;'D@:VYO=W,@86)O=70@ M=&AE(&EN=&5R;F%L(&)U9F9E<BX*"B\O(%1H:7,@<')O8FQE;2!H87,@8F5E M;B!D:7-C=7-S960@:6X@=&AE($UI8W)O<V]F="!N97=S(&=R;W5P<RX@($IA M<V]N(%-H:7)K+ HO+R!F<F]M('1H92!60RLK($-O;7!I;&5R(%1E86TL('!R M;W9I9&5D('1H92!F;VQL;W=I;F<@55),+"!P;VEN=&EN9R!T;R!A(')E<&QY M"B\O('1O('-O;65T:&EN9R!W:71H('1H92!S=6)J96-T(")A=71O97AP+F1A M="!I<R!W<F]N9R!F;W(@<W1D.F)A<VEC7W-T<FEN9R(N"@HO+R!H='1P.B\O M8V]M;75N:71I97,N;6EC<F]S;V9T+F-O;2]N97=S9W)O=7!S+W!R979I97=& M<F%M92YA<W _24-0/6US9&XF<TQ#240]=7,F<V=R;W5P55),/6UI8W)O<V]F M="YP=6)L:6,N9&]T;F5T+FQA;F=U86=E<RYV8R9S365S<V%G94E$/24R-3-# M96@E,C4R-$Y";5IT0DA!+C(V-3) =&MM<V9T;F=P,#,E,C4S10H*+R\@5&AA M="!T96QL<R!H;W<@=&\@9FEX('1H92!P<F]B;&5M+"!A;F0@9VEV97,@<V]U M<F-E(&-O9&4@9F]R(&1O:6YG('-O+@HO+R!5;F9O<G1U;F%T96QY('1H92!S M;W5R8V4@8V]D92!I<R!M;W-T;'D@=')U;F-A=&5D(&%N9"!N;W0@=7-E9G5L M+B @22!G;W0@;'5C:WD*+R\@06YD(&9O=6YD(&$@8V]U<&QE(&]F(&-O;7!L M96UE;G1A<GD@9G)A9VUE;G1S(&%N9"!P:65C960@:70@=&]G971H97(N("!4 M:&ES"B\O(&9I;&4@:7,@;7D@861A<'1A=&EO;B!O9B!T:&%T("TM('=I=&@@ M82!F97<@;6EN;W(@='=E86MS(&%N9"!S;VUE('1U=&]R:6%L(&-O;6UE;G1S M+@H*+R\@5&\@9FEX('1H92!P<F]B;&5M+"!A<W-U;6EN9R!T:&ES(&9I;&4@ M:7,@;F%M960@(D5%4W1D4W1R:6YG+F-P<"(Z"B\O"B\O(#$I($-R96%T92!A M;B!A9&0M:6X@1$Q,(&)Y(&-O;7!I;&EN9R!T:&ES(&9I;&4@=VET:"!T:&4@ M8V]M;6%N9#H*+R\)"6-L("],1" O14AS8R O3S(@1453=&13=')I;F<N8W!P M"B\O"B\O(#(I(%!L86-E('1H92!$3$P@96ET:&5R.@HO+PD)*BD@3VX@>6]U M<B!S96%R8V@@<&%T: HO+PHO+PD)*BD@26X@=&AE(&1I<F5C=&]R>2!T:&%T M(&AO;&1S(&1E=F5N=BYE>&4@+2T@=&AE(&1E9F%U;'0@;&]C871I;VX@:7,* M+R\)"2 @($,Z7%!R;V=R86T@1FEL97-<36EC<F]S;V9T(%9I<W5A;"!3='5D M:6\@+DY%5%Q#;VUM;VXW7$E$10HO+PHO+R S*2!%9&ET('1H92!A=71O97AE M<"YD870@9FEL92 M+2!T:&4@9&5F875L="!L;V-A=&EO;B!I<R!I;@HO+PD) M"4,Z7%!R;V=R86T@1FEL97-<36EC<F]S;V9T(%9I<W5A;"!3='5D:6\@+DY% M5%Q#;VUM;VXW7%!A8VMA9V5S7$1E8G5G9V5R"B\O"B\O"0DJ*2!#;VUM96YT M(&]U="!T:&4@97AI<W1I;F<@<&5R=&EN96YT(&QI;F4Z"B\O"0D@("!S=&0Z M.F)A<VEC7W-T<FEN9SQC:&%R+'-T9#HZ8VAA<E]T<F%I=',\8VAA<CXL<W1D M.CIA;&QO8V%T;W(\8VAA<CX@/CT\7T)X+E]"=68^"B\O"B\O"0DJ*2!!9&0@ M=&AE(&9O;&QO=VEN9R!L:6YE+"!W:&EC:"!W:6QL('5S92!T:&4@1$Q,('EO M=2!P<F]V:61E9#H*+R\)"2 @('-T9#HZ8F%S:6-?<W1R:6YG/&-H87(L<W1D M.CIC:&%R7W1R86ET<SQC:&%R/BQS=&0Z.F%L;&]C871O<CQC:&%R/B ^/21! M1$1)3BA%15-T9%-T<FEN9RYD;&PL7T%U=&]%>'!3=&13=')I;F= ,C@I"B\O M"B\O"0DJ*2!4:&4@96YT<GD@<&]I;G0@;F%M92!M=7-T(&UA=&-H(&5X86-T M;'DL(&EN8VQU9&EN9R!C87-E+"!T:&%T(&=I=F5N(&)Y.@HO+PD)"0ED=6UP M8FEN("UE>'!O<G1S($5%4W1D4W1R:6YG+F1L; H*+R\@5&AE<F4@:7,@5FES M=6%L($,K*R!H96QP(&9O<B!M86MI;F<@86X@861D+6EN($1,3"X@(%-E92 B M145!9&1);B!S86UP;&4@*&1E8G5G9VEN9RDB+@HO+R!4:&4@=&]P:6,@:&%S M(&)O=&@@82!D97-C<FEP=&EO;B!A;F0@<V%M<&QE(&-O9&4N("!!="!T:&4@ M=&]P+"!I="!M96YT:6]N<R!T:&4@861D+6EN"B\O($1,3"!B96EN9R!I;B!T M:&4@<V%M92!D:7)E8W1O<GD@87,@875T;V5X<"YD870@+2T@:6=N;W)E('1H M870N("!!="!T:&4@8F]T=&]M+"!I= HO+R!S87ES('1H92!S86UE('1H:6YG +(&%S("@R*2X*"@H` ` end

Christopher Woods wrote:
Jeff, Since you are using the Visual Studio products there is an option might get you where you want to be w/out requiring *any* intrusive modification in your code (or to boost). It is possible to write custom 'Add-in' DLLs to help the debugger display values in the IDE.
I'm attaching a sample that I pieced together from a couple different posts. <snip>
Chris, Thanks for the idea. This is an approach I had not known about. Thankfully, Dave Deakin's autoexp.dat addition works. I'll keep this in mind for the future. Jeff Faust

Jeffrey Faust wrote:
Thanks for the idea. This is an approach I had not known about. Thankfully, Dave Deakin's autoexp.dat addition works. I'll keep this in mind for the future.
I've not worked with 2005 much yet so it's possible that what I've suggested has been replaced by the "visualizer" that Dave Deakin provided. I'll have to keep that his suggestion in mind too :P -Chris
participants (12)
-
Christopher Woods
-
David Deakins
-
Fernando Cacciola
-
Giovanni Piero Deretta
-
Jeff Garland
-
Jeffrey Faust
-
Joe Gottman
-
Mathias Gaunard
-
Michael Fawcett
-
Thomas Witt
-
Thorsten Ottosen
-
Ulrich Eckhardt