Visual Studio natvis 语句的局部变量

Posted

技术标签:

【中文标题】Visual Studio natvis 语句的局部变量【英文标题】:Local variables for Visual studio natvis statements 【发布时间】:2020-04-19 09:54:39 【问题描述】:

我目前正在为 natvis 中的日期类型编写可视化工具。 date 类型以通常的 unix 方式存储自 1970 年以来的秒数,但如果不使用临时变量,则从中派生年、月和日是非常冗长的。我希望能够存储工作变量,以便以理智的方式评估可视化器。这可能吗?

我得到的解决方案是这样的:

struct SLowResAbsoluteTime

    SLowResAbsoluteTime() : mTime(0)  calcDOE(); 
    SLowResAbsoluteTime(int year, SDate::EMonth m, SDate::EDayOfWeek day, UINT8 hour, UINT8 minute, UINT8 seconds);
    SLowResAbsoluteTime(const SDate &date);
    SLowResAbsoluteTime(unsigned long long time) : mTime(time)  calcDOE(); 
    SLowResAbsoluteTime(const SLowResAbsoluteTime &other) : mTime(other.mTime)  calcDOE(); 

    SDate getDate() const; //calculate date object from given time
    UINT32 getHour() const; 
    UINT32 getMinutes() const;
    UINT32 getSeconds() const;

    bool operator < (const SLowResAbsoluteTime &other) const  return mTime < other.mTime; 
    bool operator > (const SLowResAbsoluteTime &other) const  return mTime > other.mTime; 
    bool operator <= (const SLowResAbsoluteTime &other) const  return mTime <= other.mTime; 
    bool operator >= (const SLowResAbsoluteTime &other) const  return mTime >= other.mTime; 
    bool operator == (const SLowResAbsoluteTime &other) const  return mTime == other.mTime; 
    bool operator != (const SLowResAbsoluteTime &other) const  return mTime != other.mTime; 
    SLowResAbsoluteTime operator -(const SLowResAbsoluteTime &time) const  return SLowResAbsoluteTime(mTime - time.mTime); 
    SLowResAbsoluteTime operator +(const SLowResAbsoluteTime &time) const  return SLowResAbsoluteTime(mTime + time.mTime); 
    const SLowResAbsoluteTime &operator -=(const SLowResAbsoluteTime &time)  mTime -= time.mTime; return *this; 
    const SLowResAbsoluteTime &operator +=(const SLowResAbsoluteTime &time)  mTime += time.mTime; return *this; 
    unsigned long long mTime;
    void invalidate()  mTime = -1; 
    bool isValid() const return mTime != UINT64(-1); 
    operator unsigned long() const  return (long)mTime; 
    void calcDOE();
#ifdef USING_DEBUG_TIMER_DOE
    struct  UINT16 y; UINT8 m; UINT8 d;  mDOE;
#endif
;

注意“USING_DEBUG_TIMER_DOE”部分。是这样计算的:

void SLowResAbsoluteTime::calcDOE()

#ifdef USING_DEBUG_TIMER_DOE
    int ts = mTime / (60 * 60 * 24);
    int z = ts + 719468;
    int doe = (z - ((z >= 0 ? z : z - 146096) / 146097) * 146097);
    int yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;  // [0, 399]
    int era = (z >= 0 ? z : z - 146096) / 146097;
    int y = (yoe) + era * 400;
    int doy = doe - (365 * yoe + yoe / 4 - yoe / 100);                // [0, 365]
    int mp = (5 * doy + 2) / 153;                                   // [0, 11]
    int d = doy - (153 * mp + 2) / 5 + 1;                             // [1, 31]
    int m = mp + (mp < 10 ? 3 : -9);                            // [1, 12]
    mDOE.y = y + (m <= 2);
    mDOE.m = m;
    mDOE.d = d; 
#endif  

用于可视化这些的 natvis 是:

<Type Name="SLowResAbsoluteTime">

    <DisplayString>time =  (mTime / (60 * 60)) % 24  :(mTime / 60) % 60:mTime % 60  day-1970: mTime / (60 * 60 * 24) </DisplayString>

    <Expand>        
        <Item Name="month">(int)mDOE.m</Item>
        <Item Name="day">(int)mDOE.d</Item>-->
        <Item Name="secs since 1/1/1970"> mTime</Item>  
    </Expand>
</Type>

【问题讨论】:

事实证明,由于溢出,不可能以疯狂的长手方式做到这一点,无论如何都要对数学进行认真的修改,而且为此付出了太多的努力。我已经通过在 NatVis 可以处理的调试版本的 C++ 代码中添加额外的变量来“解决”这个问题,但我想知道那里是否有一些更强大的技巧。像 python 或 js 这样的完整脚本语言会很有用。 你能分享一个minimal reproducible example/你到目前为止编码的内容吗!? 当然,我已经编辑了原始帖子以展示我的所作所为 【参考方案1】:

如果您想从您的代码中消除calcDOEmDOE 并在适当的natvis 中进行计算 - 是的,这是可能的。使用Intrinsic函数:

  <Type Name="SLowResAbsoluteTime">
    <Intrinsic Name="ts"   Expression="mTime / (60 * 60 * 24)                                       "/>
    <Intrinsic Name="z"    Expression="ts() + 719468                                                "/>
    <Intrinsic Name="doe"  Expression="(z() - ((z() &gt;= 0 ? z() : z() - 146096) / 146097) * 146097)"/>
    <Intrinsic Name="yoe"  Expression="(doe() - doe() / 1460 + doe() / 36524 - doe() / 146096) / 365"/>
    <Intrinsic Name="era"  Expression="(z() &gt;= 0 ? z() : z() - 146096) / 146097                  "/>
    <Intrinsic Name="y"    Expression="yoe() + era() * 400                                          "/>
    <Intrinsic Name="doy"  Expression="doe() - (365 * yoe() + yoe() / 4 - yoe() / 100)              "/>
    <Intrinsic Name="mp"   Expression="(5 * doy() + 2) / 153                                        "/>
    <Intrinsic Name="d"    Expression="doy() - (153 * mp() + 2) / 5 + 1                             "/>
    <Intrinsic Name="m"    Expression="mp() + (mp() &lt; 10 ? 3 : -9)                               "/>
    <Intrinsic Name="DOEy" Expression="y() + (m() &lt;= 2)                                          "/>
    <Expand>
      <Item Name="day">d()</Item>
      <Item Name="month">m()</Item>
      <Item Name="year">DOEy()</Item>
    </Expand>
  </Type>

【讨论】:

啊,看看那个,正是我想要的。我不知道“内在”关键字,在我阅读的文档中没有遇到它。

以上是关于Visual Studio natvis 语句的局部变量的主要内容,如果未能解决你的问题,请参考以下文章

如何将单个字符的 natvis 限制为仅 Visual Studio 中的字符

访问 Visual Studio ImageWatch 插件的 .natvis 文件中的矢量基础数据

Visual Studio natvis 显示指向接口的指针

在Visual Studio 2013中是否有用于调试Qt 4.8项目的非官方可视化工具?

Visual Studio 2019 UTF-8编码调试显示中文

在 Visual Studio 2015 调试器中查看 Qt5.6 QStrings