debugging 调试C++协程时CodeLLDB的奇怪行为

kgsdhlau  于 2023-03-30  发布在  其他
关注(0)|答案(1)|浏览(145)

就我的经验而言,给定代码行上的断点意味着调试器第一次在该行上中断时,该行 * 没有任何 * 内容正在执行,或者,换句话说,当调试器在断点处停止时,它会在执行该行代码 * 之前 * 停止,而不是 * 在该行代码 * 之后 * 或 * 在该行代码 * 中间 * 停止。
我不认为我曾经见过这种观点是矛盾的(尽管我的经验主要是C++,所以这就是我一直在调试的)。
然而,当涉及协程时,情况似乎并非如此。
this code from a previous question of mine为例(它是坏的,因为代码有UB,但我所描述的问题发生在它被触发之前,所以这并不重要),其目标摘录如下:

class [[nodiscard]] CoroTaskSub {
  …
 public:
  …
  CoroTaskSub(auto h)
   : hdl{h} {
  }
  …
};
CoroTaskSub coro() {
  …
}

CoroTaskSub callCoro() {
  std::cout << "  callCoro(): CALL coro()\n";
  co_await coro();
  …
}

我做了以下工作:
1.在cout行放置断点
1.在co_await行放置断点
1.运行程序(此时调试器在这两个断点中的第一个断点处停止)
1.在: hdl{h} {行,即在CoroTaskSub类的构造函数中放置断点¹
1.继续执行程序
在这一点上,我期望调试器会在co_await行的断点处中断,在该行的任何内容被计算之前,但是它在CoroTaskSub的构造函数上中断了一个断点,就像coro()已经被处理一样。
有点奇怪,不是吗?
你知道为什么会这样吗?
(¹)由于程序的结构,在main中调用callCoro()时,控制已经在这里传递过一次,但我只在这里放置断点,因为我想看看什么时候调用这个构造函数来构造coro()CoroTaskSub

eoigrqb6

eoigrqb61#

与常规函数不同,在协程函数中,创建返回值对象是 * 第一件事 * 发生的(好吧,在创建promise和一些簿记之后)。这是在协程中的任何代码行之前,甚至在initial_suspend点之前。这是通过调用promise的get_return_object函数来完成的。
这是必要的,因为在initial_suspend点 * 挂起 * 的情况下,返回值对象需要是调用者的有效对象。

相关问题