我在GDB中遇到了一些麻烦。我已经在ffmpeg库中构建了一个示例程序,其中包含调试符号并将其剥离。虽然我将ffmpeg库配置为静态并显式禁用了共享,但看起来我正在调试的程序是动态链接的,因为它的文件大小只有99kB。我不知道这是问题,但想提一下。
在av_seek_frame中设置并点击断点后,我使用'next'命令跳过。但是,这将进入av_seek_frame()中的第一个函数,如下所示。此外,如果做第二个“下一个”,则回溯将无法跟踪它的位置。我设置错了吗?我怎么能跨过去?我应该注意,我仔细检查了'set step-mode off'是默认关闭的(因为我相信这会在没有调试信息的第一段代码中断开。)
Breakpoint 1, av_seek_frame (s=0x16429000, stream_index=0, timestamp=29727438, flags=0) at l
(gdb) list
1648
1649 return 0;
1650 }
1651
1652 int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags
1653 {
1654 int ret;
1655 AVStream *st;
1656
1657 ff_read_frame_flush(s);
(gdb) next
ff_read_frame_flush (s=0x16429000) at libavformat/utils.c:1248
(gdb) list
1243
1244 /**
1245 * Flush the frame reader.
1246 **/
1247 void ff_read_frame_flush(AVFormatContext *s)
1248 {
1249 AVStream *st;
1250 int i, j;
1251
1252 flush_packet_queue(s);
(gdb) next
ff_read_frame_flush (s=0x16429000) at libavformat/utils.c:1252
(gdb) where
#0 ff_read_frame_flush (s=0x16429000) at libavformat/utils.c:1252
#1 0x00000000 in ?? ()
答案 0 :(得分:1)
如果您不确定您的二进制文件是否是静态链接的,可以使用ldd进行检查并查看如下消息:
% ldd ffmpeg
not a dynamic executable
接下来,请确保为gdb提供可执行文件的完整路径,这样您就不会意外地选择安装在PATH中的系统上其他位置的二进制文件。
很可能你加载了错误的二进制文件。即使没有使用--disable-stripping和--disable-optimizations,我也可以使用step
和next
命令来使用gdb。您不需要使用--disable-stripping,因为在gdb中您可以使用ffmpeg_g二进制文件(或者如果您碰巧运行ffmpeg二进制文件,则可以使用file ffmpeg_g
从中加载符号。)
出于调试目的,最好使用--disable-optimizations,以便在检查变量时不会得到value optimized out
,但严格来说,您不需要使用该选项来获取emacs / gdb表现...我在使用优化时逐步完成代码没有问题。
但是,有一件事需要记住,当在Emacs中使用gud / gdb设置断点时可能会导致混淆:gud-break
命令仅使用文件名的基本部分来设置断点,而不是它的绝对路径,在ffmpeg的情况下意味着,例如,如果在utils.c中设置断点,它可能无法正常工作,具体取决于您在gdb中设置的源代码搜索路径的值,因为ffmpeg在不同的路径中有多个名为utils.c的文件(事实上,总共有5个utils.c文件,每个lib *子目录中有一个)。默认情况下,搜索路径设置为$ cdir:$ cwd,但是如果你将它设置为类似/ path / to / ffmpeg:$ cdir:$ cwd并尝试在libavformat的utils.c中设置断点,它可能会在libavutil中找到它 - 在这种情况下,如果你很幸运,它会抱怨你想要设置断点的行不存在(因为libavutil中的那个更短),或者它可能设置一个断点你想要的那一行,但在错误的utils.c。
gud / gdb的这个问题应该被视为一个bug。当我得到片刻时,我会提交gud-break / gud-format-command的补丁来解决问题。