我有一个名为size_t A::m() const
的非静态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行,当'a.m()&gt; 1'是真的
此表达式具有副作用,不会被评估。
请注意A::m()
不会修改任何内容,它只调用向量的.size()
方法并返回该值,因此表达式具有副作用的断言完全是假的。事实上,用a.myvec.size() > 1
替换断点条件(即方法本身的内容)具有相同的效果!
关于什么可以用作断点中的条件,Microsoft says that;
条件可以是由其识别的任何有效表达式 调试器。
所以我去看看Expressions in the Debugger和found this:
副作用的一个常见原因是评估a中的函数调用 调试器窗口。这种评估通常是显而易见的。更多 副作用的微妙原因是对性质和其他的评价 托管代码中的隐式函数调用。
调试器无法判断属性是评估还是隐式 函数调用有副作用。因此,默认情况下,调试器 不会自动评估隐式函数调用。属性 默认情况下允许评估,但可以在选项中关闭 对话框。当尚未评估函数调用或属性时,a 出现刷新图标。您可以手动评估表达式 单击刷新图标。有关详细信息,请参见如何:刷新监视 值。
转换属性或隐式函数调用的评估时 off,您可以使用ac格式修饰符强制进行评估(对于C# 只要)。见Format Specifiers in C#.
如果有人可以将上段翻译成英文,那就太棒了。我可以将函数放入这些调试器条件中吗?
答案 0 :(得分:8)
以下是您提供的帮助链接的翻译版本:
,ac
。所以,归结起来的是,如果你想在你的评估中调用一个函数并使用C#,那就把,ac
放在它之后
a->m() > 1,ac
由于您使用的是C ++,我认为这可以归结为“评估报告中没有功能!”出于调试的目的,可能可以从A::m
中删除const,因为说明符不会(不应该)对逻辑流有任何影响。我不确定这是否会奏效。
答案 1 :(得分:8)
评估任何函数调用都有副作用,因为它会在寄存器或堆栈中或两者中引起状态更改。这正是你引用的最后一段所说的。
在您的情况下,假设标准项目设置,寄存器和堆栈都会更改。 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()
在此应用程序中的任何位置进入调试器,它将显示“此表达式具有副作用且不会被评估。”
答案 2 :(得分:2)
翻译语句有很好的答案,但这是一个很好的黑客可以使用。
在要添加断点的代码中,添加一行,例如
debug > 1
在那里设置一个断点,你可以在条件
中添加它if (a.m() > 1)
bool debug = 1;
或者你可以做这样的事情
.factory('AuthoringState', function() {
var track = 0;
var _pool = {};
return {
addChange : function(data) {
track++;
var temp = _.cloneDeep(data);
_pool[track] = temp;
temp['track'] = track;
return _pool[track];
},
undo : function(checklist) {
if(checklist['track'] === 1) {
return checklist;
}
return _pool[checklist['track'] - 1];
},
back : function(checklist) {
if(checklist['track'] === track) {
return checklist;
}
return _pool[checklist['track'] + 1];
}
}
})
并可以在调试行中设置断点。
答案 3 :(得分:1)
在黑暗中拍摄,但您可能希望更深入地查看方法声明中const
的使用。您可能希望显式声明任何不能更改为const的内容(IIRC正确const可以在方法声明中的五个不同位置使用,因此请仔细查看)。
const
是编译器强制执行的合同。如果您的方法访问任何非const的指针,则可能是一个问题。如果存在可能存在问题的静态变量。也有可能虽然你的编译器可能很高兴你的代码中的const很好,但IDE可能不像编译器那样聪明(因此可能需要更多的const
保证)。
如果没有你的代码,那肯定很难说,但这至少应该给你一个想法。
有关const
的更多阅读,此页面似乎有一个不错的教程: