11

我有一个名为 的非静态 const 方法size_t A::m() const,如果它返回大于 1 的值,我想用它来触发断点。下面是class A实例a

class A
{
public:
    std::vector<double> myvec;
    size_t m() const
    {
      return myvec.size();
    }
} a;

所以我在这个条件下在 Visual Studio 2013 中添加了一个断点

a.m() > 1 // a is an instance of class A

但是,当我尝试编译它时,我从 IDE 收到以下消息:

无法设置以下断点:

在 myFile.cpp,第 xxx 行,当 'am() > 1' 为真时

这个表达式有副作用,不会被计算。

请注意,A::m()它不修改任何内容,它只调用.size()向量的方法并返回该值,因此表达式具有副作用的断言完全是错误的。其实把断点条件换成a.myvec.size() > 1(即方法本身的内容)也是一样的效果!

关于什么可以用作断点中的条件,微软表示

条件可以是调试器识别的任何有效表达式。

所以我去看了调试器中的表达式发现了这个

副作用的一个常见原因是在调试器窗口中评估函数调用。这样的评价通常是引人注目的。副作用的一个更微妙的原因是对托管代码中的属性和其他隐式函数调用的评估。

调试器无法判断属性评估或隐式函数调用是否有副作用。因此,默认情况下,调试器不会自动评估隐式函数调用。默认情况下允许属性评估,但可以在“选项”对话框中关闭。当尚未评估函数调用或属性时,会出现一个刷新图标。您可以通过单击刷新图标手动评估表达式。有关详细信息,请参阅如何:刷新观察值。

关闭属性评估或隐式函数调用时,可以使用 ac 格式修饰符强制评估(仅适用于 C#)。请参阅C# 中的格式说明符。

如果有人可以将以上段落翻译成英文,那就太好了。我可以将函数放入这些调试器条件中吗?

4

4 回答 4

10

这是我对您提供的帮助链接的翻译:

  • 第 1 段:调用函数可能有副作用。评估属性可能会产生副作用。
  • 第 2 段:调试器无法判断是否有副作用,所以我们只是假设:“functions = bad”,“properties = good”(即“函数有副作用,properties 没有”)。刷新与当前问题无关的图标信息。
  • 第 3 段:想强制调试器?如果您使用的是 C#,,ac请在评估之后放置。

因此,归结为,如果您想在评估中调用一个函数并使用 C#,请将其放在,ac后面

a->m() > 1,ac

由于您使用的是 C++,我认为这归结为“您的评估语句中没有函数!” 出于调试的目的,您可以从 const 中删除 const A::m,因为说明符不会(不应该)对逻辑流程产生任何影响。不过,我什至不确定这是否会奏效。

于 2013-11-04T23:20:47.417 回答
9

评估任何函数调用都有副作用,因为它会引起状态的变化,无论是在寄存器还是堆栈中,或两者兼而有之。这正是你引用的最后一段所说的。

在您的情况下,假设标准项目设置,寄存器和堆栈都已更改。使用一条call指令调用m(),将指令指针压入堆栈,返回值存放在eax. 除了这两个明显的副作用之外,堆栈和寄存器也被为调用约定生成的序言/尾声所修改m

这可以通过生成一个裸函数并使用内联汇编程序来验证,该汇编程序只修改寄存器:

int __declspec(naked) foo()
{
    __asm
    {
        mov eax, 10
        jmp ebx
    }
}

int main()
{
    __asm
    {
        mov ebx, cnt
        jmp foo
    }
cnt:
    return 0;
}

如果您在监视列表中的任何位置进入此应用程序中的调试器foo(),它将显示“此表达式有副作用,不会被评估。”

于 2013-11-05T00:30:51.493 回答
2

翻译该声明有很好的答案,但这是有人可以使用的不错的技巧。

在要添加断点的代码中,添加一行,例如

auto debug = a.m()

在那里设置一个断点,您可以在条件中添加它

debug > 1

或者你可以做这样的事情

if (a.m() > 1)
    bool debug = 1;

并且可以在调试行设置断点。

于 2016-08-26T17:58:37.630 回答
1

这里是在黑暗中拍摄的,但您可能希望const更深入地查看方法声明中的使用。您可能想要显式声明任何不会更改为 const 的内容(IIRC 正确 const 可以在方法声明中的五个不同位置使用,因此请仔细查看)。

const是编译器强制执行的合同。如果您的方法访问任何不是 const 的指针,则可能会出现问题。如果有一个可能有问题的静态变量。也有可能您的编译器可能很高兴 const 在您的代码中很好,但 IDE 可能不如编译器智能(因此可能需要更多const保证)。

没有您的代码,很难确定,但这至少应该给您一个想法。

对于更多的阅读const,这个页面似乎有一个不错的教程:

http://www.cprogramming.com/tutorial/const_correctness.html

于 2013-11-04T23:10:03.457 回答