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】:如果您想从您的代码中消除calcDOE
和mDOE
并在适当的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() >= 0 ? z() : z() - 146096) / 146097) * 146097)"/>
<Intrinsic Name="yoe" Expression="(doe() - doe() / 1460 + doe() / 36524 - doe() / 146096) / 365"/>
<Intrinsic Name="era" Expression="(z() >= 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() < 10 ? 3 : -9) "/>
<Intrinsic Name="DOEy" Expression="y() + (m() <= 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项目的非官方可视化工具?