gdb调试解决找不到源代码的问题 您所在的位置:网站首页 gdb打印代码内容 gdb调试解决找不到源代码的问题

gdb调试解决找不到源代码的问题

2024-01-18 02:42| 来源: 网络整理| 查看: 265

文章目录 前言找到源代码的必要性涉及到的命令gdb怎样找源代码源代码目录集合源代码文件目录集合的默认值查看各种目录查看源代码文件名和编译目录查看源代码搜索目录查看当前目录 具体示例使用 dir 命令解决使用 cd 命令解决使用 set substitute-path 命令解决 总结

前言

通过 gdb 启动程序,打好断点运行,开始调试输入 list 命令,结果发现找不到源代码,是不是很糟心,让我们来看看怎么解决这种情况。

先來说明我们要处理的情况,调试程序找不到源代码首先你得有源代码,如果编译完程序你把源代码删了,或者单独把执行程序拷贝到一个没有源代码的机器上,那么拜拜吧您嘞,这种情况不是本文能解决的。

如果你确实有源代码,正常编译源代码并且加入了 -g 选项,编译完之后没有改变源代码位置,那么调试的时候基本都会找到源代码,所以这种情况也不在我们的讨论范围之内。

分析到现在就剩下一种情况,程序编译完成之后我移动了代码的位置。实际工作中可能不会这么无聊,故意改变目录位置让调试程序找不到,但是工作中常常会出现发布机编译完代码要在开发机调试的情况,两台机器上的代码时一样的,但是源代码的位置可能放置的不同,那么在个人开发机上调试这样的程序就会找不到源代码,这也就是我们要解决的问题。

找到源代码的必要性

其实在我看来找不到源代码的问题没有那么严重,编译程序里记录了文件名,行号等信息,可以在调试的时候对照着本地的源代码进行“盲调”,这种“盲调”的操作之前可没少干,因为线上环境中没有源代码,我只能一边对照着 gdb 调试输出的行号,一边对照本地的源代码进行程序分析,通过这种方法也解决了不少问题。

虽然看着源代码调试没有那么必要,但是如果可以看见那肯定是更好了,所以本文还是列举出最常见的处理方法,解决一下本来有代码,但因为目录不匹配无法正常调试的问题。

涉及到的命令

下面几个命令是 gdb 命令,注意要放到和 gdb 交互命令行输入才可以,别管会不会,先混个脸熟,以后要经常用的:

show dirdir 目录set dir 目录1:目录2:目录3dirpwdcd 目录set substitute-path from-path to-path gdb怎样找源代码

有时候很奇怪,代码明明就在那里,gdb 你睁开眼睛行不行,为什么你就是找不到呢?其实 gdb 也很苦的好不好,一直帮你查问题还要忍受着你每天的埋怨,到底是什么原因导致 gdb 对眼前的代码视而不见呢?

其实 gdb 查找代码也要遵循一定的规则,不能每次都全盘扫描吧,那不是得给它累死。举个例子吧,我们在安装一些软件,特别是一些命令行工具的时候,总是有一步要求你把工具或软件所在目录添加到环境变量中,这个变量的名字叫做 Path。

这个 Path 其实就是电脑上众多软件所在目录的集合,当你直接使用软件的程序时,会优先从 Path 这个集合中的目录下去找,成功找到就会直接调用,否则提醒你软件不存在。

源代码目录集合

而在 gdb 的调试过程中也有这样一个目录集合,我暂且称它为 SourcePathSet,后面就用这个名字了,因为还要涉及到多种查找目录,请注意区分。

gdb 在查找源码的时候首先在 SourcePathSet 中所包含的目录下找,如果找不到就会提示查找失败了,也就是这篇文章所提到的问题。

源代码文件

程序在编译的过程中会记录源文件的名字和路径,这个路径可能是绝对路径,比如 /mnt/d/main.cpp,也可能是相对路径 ../main.cpp ,究竟是哪一种取决于编译时使用的参数。

我们以绝对路径为例,比如文件名为 /mnt/d/main.cpp,我们可以把它拆分成包含路径和不包含路径两种形式:/mnt/d/main.cpp 和 main.cpp,当 SourcePathSet 中包含一个路径叫 /mnt/e时, gdb 搜索的路径包括以下几种:

/mnt/d/main.cpp/mnt/e/mnt/d/main.cpp/mnt/e/main.cpp

当源文件是相对路径 ../main.cpp 的时候,那么搜索的路径就变成了下面两个:

/mnt/e/../main.cpp/mnt/e/main.cpp

说到这里你可能就明白了,当 gdb 找不到源文件的时候,修改 SourcePathSet 就可以了,把想让它搜索的路径添加到 SourcePathSet,如果符合它的搜索规则,那么就可以找到了。

目录集合的默认值

SourcePathSet 在 gdb 启动后开始生效,默认值并不是空,而是 $cdir:$cwd,这又是什么鬼?其中的 $cdir 叫做编译目录,是代码在编译时记录到程序中的,$cwd 表示当前的调试目录,可以通过 cd 命令来修改,要注意这个 cd 修改的是 gdb 会话中的当前目录,不会影响启动 gdb 前文件系统中的目录位置。

假设 $cdir 的值是 /usr,cwd 的值是 /home/albert,我们又添加了 /mnt/e 到 SourcePathSet 中,那么此时 SourcePathSet 的值为 /mnt/e:$cdir:$cwd,如果源文件的是 /mnt/d/main.cpp,查找的目录就会出现以下几种:

/mnt/d/main.cpp/mnt/e/mnt/d/main.cpp/usr/mnt/d/main.cpp/home/albert/mnt/d/main.cpp/mnt/e/main.cpp/usr/main.cpp/home/albert/main.cpp 查看各种目录

先做一下准备工作,编写一段简单代码,另存文件名为 main.cpp,保存在目录 /mnt/d/cpp 下:

#include using namespace std; int main() { int a = 1; int b = 2; int c = a + b; cout public: int add(int a, int b); }; //mymath.cpp #include "mymath.h" int mymath::add(int a, int b) { int c = a + b; return c; }

在 /mnt/d/mainpro 目录下编译代码,然后将代码文件所在目录 core 和 kit 拷贝到 /mnt/e/newpro 目录下,将可执行文件拷贝到 /home/albert 目录下。

albert@home-pc:/mnt/d/mainpro$ g++ /mnt/d/mainpro/core/mainpro.cpp /mnt/d/mainpro/kit/mymath.cpp -g -o mainpro albert@home-pc:/mnt/d/mainpro$ tree . |-- core | `-- mainpro.cpp |-- kit | |-- mymath.cpp | `-- mymath.h `-- mainpro 2 directories, 4 files albert@home-pc:/mnt/d/mainpro$ mkdir /mnt/e/newpro albert@home-pc:/mnt/d/mainpro$ sudo mv core/ /mnt/e/newpro/ albert@home-pc:/mnt/d/mainpro$ sudo mv kit/ /mnt/e/newpro/ albert@home-pc:/mnt/d/mainpro$ mv mainpro /home/albert/

在 /home/albert 目录下启动 gdb 开始调试,先在 main 函数打断点,查询源文件路径和编译目录等信息;

albert@home-pc:~$ gdb -q mainpro Reading symbols from mainpro...done. (gdb) b main Breakpoint 1 at 0x4008de: file /mnt/d/mainpro/core/mainpro.cpp, line 7. (gdb) run Starting program: /home/albert/mainpro Breakpoint 1, main () at /mnt/d/mainpro/core/mainpro.cpp:7 7 /mnt/d/mainpro/core/mainpro.cpp: No such file or directory. (gdb) info source Current source file is /mnt/d/mainpro/core/mainpro.cpp Compilation directory is /mnt/d/mainpro Source language is c++. Producer is GNU C++ 5.4.0 20160609 -mtune=generic -march=x86-64 -g -fstack-protector-strong. Compiled with DWARF 2 debugging format. Does not include preprocessor macro info. (gdb) list 2 in /mnt/d/mainpro/core/mainpro.cpp (gdb) pwd Working directory /home/albert. (gdb) show dir Source directories searched: $cdir:$cwd (gdb)

果然找不到源代码了,从上面的调试信息来看,可以得到以下信息:

源代码文件为 /mnt/d/mainpro/core/mainpro.cpp程序编译目录为 /mnt/d/mainpro当前目录为 /home/albert

而源代码查找列表中只有 $cdir:$cwd,说明只包含 /mnt/d/mainpro 和 /home/albert,那么查找的目录有:

/mnt/d/mainpro/core/mainpro.cpp/mnt/d/mainpro/mnt/d/mainpro/core/mainpro.cpp/home/albert/mnt/d/mainpro/core/mainpro.cpp/mnt/d/mainpro/mainpro.cpp/home/albert/mainpro.cpp

这些目录显然找不到源代码文件了,因为文件已经被我移动到 /mnt/e/newpro/ 目录下了,也就是 /mnt/e/newpro/core/mainpro.cpp,下面来尝试一些解决方法。

使用 dir 命令解决

刚才说了源代码查找集合 SourcePathSet 中只有 $cdir:$cwd,我们可以自己加一个嘛,比如像下面这样:

(gdb) dir /mnt/e/newpro/core/ Source directories searched: /mnt/e/newpro/core:$cdir:$cwd (gdb) list 2 #include 3 using namespace std; 4 5 int main() 6 { 7 int a = 1, b = 2; 8 mymath* m = new mymath(); 9 10 int c = m->add(a, b); 11 cout 7 int a = 1, b = 2; 8 mymath* m = new mymath(); 9 10 int c = m->add(a, b); 11 cout


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有