views:

46

answers:

2

I already did some fiddling in autoexp.dat to ease the inspection of custom string and other simple classes in the Visual Studio debugger (using vs2005). I'd really love to directly see the value (or approximation) of our custom floating point class. The internal representation is a quad-integer (int mantissa[4], 128bit on x86) that will be divided by 10 to the power of our exponent. So it basically looks like this:

class FloatingPoint
{
   private:
      char exponent;
      int mantissa[4]
};

The following statement would convert it to double, given fp is an object of type FloatingPoint:

(mantissa[0] + 
   * ((double)mantissa[1] * 32 * 2) 
   * ((double)mantissa[2] * 64 * 2) 
   * ((double)mantissa[3] * 96 * 2))
   /  std::pow(10, fp.exponent)

Is it possible to somehow get the Visual Studio debugger show objects of type FloatingPoint using this calculation? The call to pow is an extra problem, because this function has no external linking and can not be called by the debugger... maybe there's a way around this?

+2  A: 

Since the range of possible exponents is so small, add a (debug-only) lookup table double power10[256];. The debugger will happily use that. Only downside: debugging constructors of global objects may happen before the array is initialized, in which case those values will still be 0. You will need to call the initializer function yourself, from the Immediate Window, if this happens.

On a slightly-related note, you'll want to choose either signed char or unsigned char for the exponent. (Probably signed, else there's no point to float). Plain char has an implementation-defined sign, and here that sign is quite relevant.

Quick attempt (not tested) :

FloatingPoint {
  preview (
    #([($c.mantissa[0]  + $c.mantissa[1] * 64.0 + $c.mantissa[2] * 128.0 + $c.mantissa[3] * 192.0) / power10[$c.exponent], f])
  )
  stringview (
    #([($c.mantissa[0]  + $c.mantissa[1] * 64.0 + $c.mantissa[2] * 128.0 + $c.mantissa[3] * 192.0) / power10[$c.exponent], f])
  )
  children([$c,!])
}
MSalters
Thanks for your answer, the lookup table is a great idea, that solves the pow()-problem. But how can I tell the debugger to always use that (relatively complex) statement to display FloatingPoint objects? Most likely it's done in autoexp.dat, but I'm not familiar with the syntax and there's no documentation.
Daniel Albuschat
Have a peek at [How to Write Native C++ Debugger Visualizers in Visual Studio for Complicated Types](http://www.idigitalhouse.com/Blog/?p=83) - you merely add a `FloatingPoint { }` section to autoexp.dat. Also have a look at [Math in autoexp.dat](http://mariusbancila.ro/blog/2007/04/06/tweaking-autoexpdat-for-custom-types-in-vs2005/)
MSalters
Thanks for this useful link, MSalters!But I got a new problem: The class I want to debug is in a library. It seems the power-of-ten-table is only available when I'm currently debugging this library's code -- while debugging code that uses this library, the symbol can not be found. Why is that and how can I circumvent it? I even exported it from the DLL
Daniel Albuschat
Looking at the `VARIANT` visualizer, I realized that you could also implement that lookup table inside autoexp.dat itself. Have a look at the `#switch ($e.vt)` statement. You would need to add a similar switch on `$e.exponent`. No bonus points for elegance, but it will work.
MSalters
Thanks, another great idea! But this still leaves me with big question marks above my head about the syntax. When do I have to use #(), when do I have to use [], etc.? I have no clue how I should formulate my calculation, since the syntax is absolutely different than anything else I've ever seen before. And the examples I could find are all very different from what I need to accomplish.
Daniel Albuschat
Hm, disregard that, actually your example above already pretty much works. It just seems that the debugger does not cope well with that many digits... I'll continue fiddling with it.
Daniel Albuschat
+2  A: 

Another approach that may work is

const char* FloatingPoint::ToString () const
{
  static char buf[64];
  double d = (mantissa[0] + 
   * ((double)mantissa[1] * 32 * 2) 
   * ((double)mantissa[2] * 64 * 2) 
   * ((double)mantissa[3] * 96 * 2))
   /  std::pow(10, fp.exponent);
  sprintf(buf, "%f", d);
  return buf;
}

which would allow Floatingpoint =<ToString()> in the [AutoExpand] section.

MSalters
Yes, a ToString already exist and could be used. But the same problem applies as described in my last comment: The function can not be found when the current debugging code is not within the library where it is defined. Is there any way to solve this?
Daniel Albuschat
Oh and by the way - I could nowhere find the correct syntax for doing this in [AutoExpand]... autoexp.dat is just so horribly documented ;(
Daniel Albuschat
How can I do this when ToString() is a non-member?
Daniel Albuschat