[C++]为什么 For 循环在调试时执行顺序像个悠悠球?

2022-03-18 18:41:20 +08:00
 ActualAvocado

一般的 for 执行顺序是 for 循环中最后一条语句执行完回到 for 循环的第一行 https://www.youtube.com/watch?v=EfXHIhP2qU0 但是这个视频中(刚上传的),这个 for 循环最后一句执行后,会反向执行,像个悠悠球一样。

我用的是 vscode 远程连接到服务器( ubuntu20.04 ) vscode launch.json 调试的工具用的是 gdb 。 源码是 源码目录 下的 evaluate.cpp

但是我为了方便调试,把第 143 行 #pragma omp parallel for 删除了。

2956 次点击
所在节点    C++
14 条回复
BrettD
2022-03-18 18:48:04 +08:00
开了优化?
ActualAvocado
2022-03-18 18:50:11 +08:00
@BrettD 是指编译器优化吗?
Inn0Vat10n
2022-03-18 19:00:49 +08:00
反向的过程是在调析构吧
zzxxisme
2022-03-18 19:06:16 +08:00
我猜反向执行是在执行 string 和 vector 的析构函数。可以试着回去的时候看看能不能 step in ?
FrankHB
2022-03-18 20:10:01 +08:00
源代码中的行和生成代码的顺序本来就不保证相同(其实都没法一一对应,因为有的可能根本不生成目标代码)。由于编译器 IL 和目标代码也不保证一一对应,指令重排序在后端也可能发生。优化可能会增加这种机会(因为不优化编译器可能会偷懒就默认源代码翻译顺序了)。默认顺序也不绝对,像 GCC 生成函数实际参数的代码中一般表现出从右到左求值,除非改-feval-order 。
既然用 gdb ,你 si 一下看看指令走的流程跟你源代码怎么对应的就是了。
ActualAvocado
2022-03-18 20:36:09 +08:00
@zzxxisme 哦哦哦 应该是这个原因了,step in 后进析构了
yulon
2022-03-18 21:17:45 +08:00
看完视频大致猜到了是在析构,一看跟帖 v2 聪明人还是很多的,编译器是可以打乱执行顺序,但是那么规律的倒序执行,肯定是有点什么原因在里面的,如果有人觉得大家的问题都不配让你动脑子你其实可以选择不回复。
LeviMarvin
2022-03-18 21:27:25 +08:00
我用 CLion 的 Debug 给 for 内语句打断点也是,根悠悠球一样,不过记录的信息挺详细的,执行一遍语句后有 ++i 的话 i 也 +1 ,虽然没什么用
noyle
2022-03-18 23:36:38 +08:00
leimao
2022-03-19 00:34:43 +08:00
C++不是 scripting language ,你看到的你写的未必就是实际被执行的。
documentzhangx66
2022-03-19 06:49:46 +08:00
每行前面加个 printf( 自增 ID )试试?这种简单粗暴的办法,让我在不便于 IDE 调试的环境下,解决了不少问题。

比如:

源代码:
int a = 1;
int b = 2;
int c + a + b ;


简单粗暴后:

printf_s( "V2EX Debug Mode - 位置 " + 1 + 换行 );
int a = 1;

printf_s( "V2EX Debug Mode - 位置 " + 2 + 换行 );
int b = 2;

printf_s( "V2EX Debug Mode - 位置 " + 3 + 换行 );
int c + a + b ;

printf_s( "V2EX Debug Mode - 位置 " + 4 + 换行 );
jackchenly
2022-03-19 08:54:48 +08:00
调用析构函数
secondwtq
2022-03-19 11:33:19 +08:00
建议楼主可以源码和汇编结合看,更方便理解。
社区上有一些 GDB 的插件,可以做到汇编和源码同屏之类的增强 ncurses UI 。VSCode 好像也有这个功能。或者 godbolt 也可以帮你把汇编和源码对应起来。
当然我个人体验这些方法的缺点是不 scalable ,源码一多就容易乱,再加上 C++ 要求编译器整很多活,稍微大点的程序就没那么直接。

我觉得归根结底是现在的 toolchain 还是比较拉,对调试信息的记录和管理简单粗暴,想要干点精细活就很麻烦。
BIAOXYZ
2022-03-19 15:45:42 +08:00
以前在 vscode 里单步时也见过,应该只是看起来是“反向执行”,其实根本没执行。你可以按这位老哥 @documentzhangx66 的建议加点打印再试试,应该不会逆序打印出来的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/841338

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX