Visual Studio Debugger 值在本机到托管转换后是错误的

问题描述

一般说明

我在调试 Visual Studio 项目时遇到问题。这个项目有一个很大的中心类“MachineControl”。它还将当前所处的状态存储为枚举类的值。 在尝试修复一个不相关的错误时,我设置了一些条件断点来解决它。经过一些混乱的情况后,我意识到我从调试器中获得的信息是错误的。代码运行的值与调试器显示的值不同。

mState shows false value in mouse-over

这个值是错误的,因为当我单步执行代码时,它实际上表现得好像它处于 StateEnum::Running(1) 状态。

IDE 和代码信息

在与调试器相关的所有内容中发现错误信息:

  • 由调试器鼠标悬停显示
  • 用于条件断点
  • 汽车
  • 当地人
  • 观看
  • “即时窗口”
  • 内存视图

正确信息:

  • std::cout
  • 代码行为
  • 记录

环境:

代码

  • MachineControl 类中的单线程本机代码
  • 托管 C++ GUI 项目调用围绕本机 C++ 静态库的托管模拟包装 DLL(这解释了后面提到的“托管到本机”转换)

代码示例

错误的调试信息发生在难以隔离的点上。可悲的是,我无法生成一个最小的可重现示例。以下代码段是我必须显示问题发生的一般情况的最少说明性代码

class MachineControl : public EventReceiver <Evt>
{
    StateEnum mState;
public:
    void onEventReceived(const Evt& evt) override;
    void processperiodicTimer();
    //...
};

void MachineControl::onEventReceived(const Evt& event) // called by other class through managed to native transition
{
    switch (mState) // shows wrong information
    {
    case StateEnum::Running:
        processRunning(event); // <-- code jumps here,even though mState is not shown to be in StateEnum::Running
        break;
   
    // handle other cases
    }
    //...
}

void MachineControl::processperiodicTimer() // called from inside
{
    switch (mState) // shows correct information
    {
        // ...
    }
   //...
}
// a thousand more lines of code before and after this

观察

  • StateEnum 的值最多定义为 18,但高于 Debug 信息中显示的值。错误显示值不符合我认可的任何模式
  • MachineControl 类包含许多“switch(mState)”的实例。通过所有这些,当调用堆栈在其下方显示 [Native to Managed Transition],然后是 [Managed to Native Transition],然后是其他一些类时,错误似乎正好发生。

Call Stack illustration

上图说明了显示错误调试信息时的调用堆栈。

我尝试和/或验证的不成功的事情

  • 项目在调试配置中运行(在类似的 StackOverflow 帖子中提到)
  • 优化已禁用 (/Od),我在网上找到的许多文章中都提到过
  • 使用标志 /clr 而不是 /clr:pure,如相关问题的答案中所述:Visual Studio Debugger displays wrong values for native types
  • 调试信息格式为“程序数据库”(/Zi)。切换到不同的格式并不能解决问题
  • 结构成员对齐在所有项目中都是相同的。在线搜索类似问题显示了一种可能导致这种对齐的情况。我检查了所有相关的项目设置。每个“#pragma pack(1)”后面跟着一个“#pragma pack()”
  • 没有其他名为“mState”的变量(在 Visual Studio showing wrong values while debugging? 中提到)
  • 以下设置已关闭:“仅启用我的代码”、“使用托管兼容模式”

如何在本地解决问题

  • 在 switch 语句前添加“auto tempState = mState”。然后 tempState 变量显示正确的值,而 mState 仍然是错误的。
  • 添加间接引用:
void MachineControl::onEventReceived(const Evt& event)
{
    usessIndirection(event);
}

void MachineControl::uselessIndirection(const Evt& event)
{
    switch (mState)
    {
        //...
    }
    //...
}

那两个“解决方案”并不令人满意,因为我不想为了使调试按预期工作而到处添加局部变量和不必要的函数调用。似乎有一个潜在的问题需要注意。

这个问题真的扰乱了我的调试工作,我很高兴听到任何建议或后续问题。谢谢!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)