英文:
Hitting breakpoints in strange order with simple code
问题
我在处理一些C++代码,发现断点的命中顺序很奇怪,我不明白为什么。我正在使用Visual Studio 2022,cl.exe版本为19.35.32215,link.exe版本为14.35.32215.0。作为一个简单的复现,我创建了一个新的C++控制台应用程序,代码如下:
#include <vector>
std::vector<int> DoSomething()
{
std::vector<int> results;
results.push_back(55);
return results;
}
int main()
{
std::vector<int> results = DoSomething();
return 0;
}
我在以下两行上设置了断点:
results.push_back(55);
return results;
当第一个断点命中时,是"return results;",让我感到非常惊讶。如果我继续执行代码,我会回到"results.push_back(55);",然后继续到"return results;"。
我预期会按照它们在代码中的顺序命中两个断点(即先是"results.push_back(55)",然后是"return results;")。我尝试了x64和x86的Debug构建,两者都出现了相同的断点怪异情况。
我还尝试检查反汇编代码,弹出一个框让我“解决歧义”:
解决歧义弹出框
我还没有尝试在gcc或clang中使用相同的代码。
有人能帮我解释一下发生了什么吗?我觉得我可能漏掉了一些显而易见的东西,但我不知道是什么。
谢谢!
英文:
I was working on some C++ code and noticed my breakpoints were getting hit in a strange order and I don't understand why. I'm using Visual Studio 2022 with cl.exe version 19.35.32215 and link.exe version 14.35.32215.0. As a simple reproduction I created a new C++ console app with the following code:
#include <vector>
std::vector<int> DoSomething()
{
std::vector<int> results;
results.push_back(55);
return results;
}
int main()
{
std::vector<int> results = DoSomething();
return 0;
}
I put breakpoints on the following two lines:
results.push_back(55);
return results;
I was very surprised when the first breakpoint hit was "return results;". If I continue code execution I bounce back to "results.push_back(55);" and then move on to "return results;" again.
I was expecting to hit my two breakpoints in their line ordering (i.e. "results.push_back(55)" first, then "return results;"). I've tried both x64 and x86 with a Debug build and both have the same breakpoint weirdness.
I also tried inspecting the disassembly and a box pops up asking me to "Resolve Ambiguity":
Resolve Ambiguity popup
I have not tried this same code with gcc or clang.
Can anyone help explain to me what's going on? I feel like I'm missing something obvious, but I don't know what.
Thanks!
答案1
得分: 3
如果在编译器中使用 /permissive-
,则即使在调试配置中也会应用可选的 NVRO。它在调用者的堆栈帧上为返回的对象分配内存,并传递指向被调用函数的指针。这可能会让调试器感到困惑,因为它可能将 return results
视为在 push_back()
之前应执行的对象构造和初始化,但 return
实际上位于代码中 push_back()
之后,因此它的行为类似于:用户在第 N 行设置断点,但我已经跳过到第 N+1 行,我必须在这里停止。
您可以使用 /Zc:nrvo-
禁用 NVRO。
英文:
If you use /permissive-
in the compiler, then it applies the optional NVRO even in the Debug configuration. It allocates memory for a returned object on the caller stack frame and passes a pointer to a called function. It can confuse the debugger, that can see return results
as object construction and initialization that of course should be performed before push_back()
, but return
is located in the code after push_back()
, so it behaves like: user set the breakpoint on the line N, but I have jumped over on the line N+1, I must stop here.
You can disable NVRO with using /Zc:nrvo-
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论