2022-04-27 在 vscode + clang64 + lldb + clangd 环境下 C++ 的 debug 方法

缘起

写代码这么长时间,回答各种 c 或 c++ 的初等问题,我有一个及其深的感受,初学者不会debug。

哪怕是最简单的问题,没有趁手的工具,你都很难解决,尤其是 c 或 c++。

clangd是个趁手的工具,去学它,那是世界上最好的老师,分分钟教你做 c++er。

gdb 或 lldb是趁手的工具,去学它,让 bug 无处躲藏。

我目前的编程环境如题目所示。如果你和我一样的环境,或想用lldb进行debug,可以继续读下去。

clangd + lldb 编程环境的建立,请移步:2022-03-30 VsCode中使用clangd插件的各种设置

开练

OK,那么假设你的环境搭建好了,你要对如下这个简单的程序进行debug:

这是一个简单的程序,输入当前时速speed和限速limit,当速度大于等于1.5倍limit时,吊销驾照,当速度大于等于1.1倍limit时,罚款200.

多么清晰。但是当你输入110 100,也就是时速110,限速100时,提示为OK!

没有收到罚单。警察叔叔放过了你。

这是不可以的,但是为什么?

一眼看去,程序逻辑清晰,基本是小学3年级算数,为啥一台如此高等的计算机就不会做。

#include 

using namespace std;

int main()
{
    int speed;
    int limit;
    double x;

    cin >> speed >> limit;

    if (speed >= limit * 1.5)
    {
        x = (speed - limit) / limit * 100;
        cout << "Exceed " << x << "%.License Revoked" << endl;
    }
    else if (speed >= limit * 1.1)
    {
        x = (speed - limit) / limit * 100;
        cout << "Exceed " << x << "%.Ticket 200" << endl;
    }
    else
    {
        cout << "OK" << endl;
    }

    return 0;
}
debug开始

轻轻按下F5,大约收到8个警告,但是编译是成功的。

我们来到终端,输入 110 100 按回车。

然后就出来了。

110 100
OK

E:\clangC++>

说好的debug呢,我们完美的错过了。

打断点

为什么完美错过,因为没有断点。为什么没有断点,因为没有打断点。怎么打断点?

在运行和调试界面,断点对话框点击 “ + ” 输入 “ main ”

这是告诉lldb,进入主函数立即停止,等待下一步命令。

你可以在这里填入任何函数!调试会在这个函数下停止,等待命令。

然后在这行代码处按 F9 断点调试框下就出现了此行代码的断点。

    else if (speed >= limit * 1.1)

你甚至可以在此行代码的左侧红点处点击鼠标右键,对断点进行编辑,比如输入

speed >= 110

那么当条件满足时,调试程序会在此行代码处停止,等待。

现在,让我们重新按 F5 进入debug,神奇的事情发生了,debug的指示标志停在了我们刚刚设置的main函数处,OK,我们继续,按F10,并在终端输入110 100 回车。

此时指示停在了我们设置的代码处:

    else if (speed >= limit * 1.1)
查变量

此时,我们查看运行和调试框中的变量:

local
  speed:110
  limit:100
  x:乱七八糟不知是啥

我们用小学数学计算一下,limit * 1.1 = 110 ,此处应有掌声。

但是,为了保险起见,我们还是查看一下,计算机眼里 limit * 1.1 究竟是多少。

查监视

我们在运行和调试框的监视中点击 " + " , 输入 limit * 1.1,神奇的事情又发生了!

这个值是:

limit * 1.1110.00000000000001

它不是110,重复,它不是110!

OK ,bug已经找到,问题的解决就在这一刻,我们要如何使得这个值等于110呢? 而它为啥不是110呢?

让我们回到 C++ 的环境,看看这句代码究竟是什么意思。

    else if (speed >= limit * 1.1)

如果 speed 大于等于 limit 乘以 1.1 则…

这是一个复合语句,先求积,再比较。而乘法的过程是一个 int 乘以一个 double,这里是重头戏,危险的隐式转换。

继而一个 int 又和一个double 比较大小,又进行隐式转换。

而且我们哪里知道,100 * 1.1 不等于 110。

是的,在计算机眼中,二者不等。

不知你的眼里是否湿润了,反正我被惊到了。比较两个double要小心,比较两个float更要小心。在浮点的语境里,只有精度值。

问题找到了,怎么办?

既然是隐式转换搞出的问题,就强制转换解决,double不能比较,就用 int。

static_cast 了解一下:

    if (speed >= static_cast<int>(limit * 1.5))

修复了这个代码,重新debug,终于不在是超速OK了。

但是超速变成 0 了,仍然罚款了。

110 100
Exceed 0%.Ticket 200

剩下的问题,就看你的了,程序是有限的,bug是无限的,以有涯随无涯,殆已。

你可能感兴趣的:(笔记,C,c++,debug)