在Qt中设置断点后,gdb显示:“访问内存地址出错”。

7

我在这里编写了一个非常简单的Qt程序:

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    QTableView table(&frame);
    table.resize(100, 100);
    table.show();

    return app.exec();
}

当我尝试在表格被点击的地方设置断点时,gdb会报错:

(gdb) symbol-file /usr/lib/libQtGui.so.4.4.3.debug 
Load new symbol table from "/usr/lib/libQtGui.so.4.4.3.debug"? (y or n) y
Reading symbols from /usr/lib/libQtGui.so.4.4.3.debug...done.
(gdb) br 'QAbstractItemView::clicked(QModelIndex const&)'
Breakpoint 1 at 0x5fc660: file .moc/release-shared/moc_qabstractitemview.cpp, line 313.
(gdb) run
Starting program: ./qt-test
Warning:
Cannot insert breakpoint 1.
Error accessing memory address 0x5fc660: Input/output error.

有人知道为什么无法插入断点吗?


我正在使用Ubuntu Intrepid,并且已经安装了libqt4-dbg,如果有帮助的话。 - Neil
4个回答

12

不要使用gdb命令symbol-file来加载外部符号。 断点地址将是错误的,因为它们没有被重定位。

相反,设置一个在main中的断点,运行程序,然后设置你的断点:

gdb ./program
GNU gdb 6.8-debian blah blah blah
(gdb) br main
Breakpoint 1 at 0x80489c1
(gdb) run
Starting program: ./program
Breakpoint 1, 0x080489c1 in main ()
(gdb) br 'QAbstractItemView::clicked(QModelIndex const&)'
Breakpoint 2 at 0xb7d24664
(gdb) continue
Continuing.

然后让您的断点发生。

确保在您要设置断点的函数中指定参数列表,但不包括这些参数的名称,只包括它们的类型。


4
感谢 pholklore 在 irc.freenode.net 的 #gdb 频道中提供了这个答案。 - Neil
你也可以在不先在main()上设置断点的情况下,仅在任何你喜欢的地方设置断点,gdb会询问你是否要设置一个待定断点。然而,这种方法你永远无法确定该函数是否真实存在,或者你是否打错了字。因此,答案中所示的方法更加安全。 - Neil

4

实际错误:

访问内存地址0x5fc660时出错:输入/输出错误。

可能是32/64位混淆导致的。例如,请检查您是否使用64位进程ID连接了32位二进制文件,或者反之亦然。


我有这个问题,但是我无法弄清楚如何正确地使用gdb :( - froginvasion
位数不匹配也不是问题吗? - Nathan Kidd
似乎我需要在makefile中添加“-g”选项,这样问题就解决了。我在stackoverflow上找到了它,但我不知道它的作用是什么。 - froginvasion
@froginvasion,-g 编译时会添加调试符号,因此允许调试器查看源代码并提供有用的反馈信息。 - tjwrona1992

2
对我来说,使用mingw-w64(本地或交叉编译器)构建时,一切都很好。我不确定确切的问题是什么,但如果我使用gcc mingw-w64 i686-5.1.0-posix-sjlj-rt_v4-rev0进行构建,则最终会创建可调试的构建。否则...
(gdb) break main
...
(gdb) r
...
Cannot insert breakpoint 1.
Cannot access memory at address 0x42445c
<process basically hangs>

19次中有18次会出现错误信息,但有时它确实可以正常工作(非常罕见)。

gdb 7.8.1和7.9.1似乎能够调试创建的exe文件。因此,可能不是gdb版本的问题。

我目前的理论/怀疑是,要么是gcc版本的问题,要么是编译器的sljl vs. dwarf2“方面”(i686-492-posix-dwarf-rt_v3-rev1无法工作,使用某种形式的gcc 4.9.2进行交叉编译也无法工作)。没有尝试其他版本的gcc。

更新:使用更新的gcc(5.1.0)进行交叉编译,但我仍然遇到了这个错误。在这种情况下,原因是我的构建(FFmpeg)通过链接使用的一个依赖库(在此情况下为libgme)导出了一些错误的“共享”符号(当我正在构建静态可执行文件时)。因此,“共享”构建会中断(请参见https://trac.ffmpeg.org/ticket/282),并且某种方式它也会损坏gdb。例如,可能链接SDL也会对您产生同样的影响。我认为可能是一个ld的错误[?]

1
我在调试VLC 3时也遇到了这个问题(但在4中没有出现)。你不能使用“start”,因为它会自动在主函数上设置断点。一个解决方法是,在它停在“无法访问内存”时,告诉它delete 1,然后continue - Gabriel Luci

2
如果您想在主函数中自动断点而无需设置断点,您也可以使用 start 命令。
如果您需要向程序提供任何参数,可以使用:
start argument1 argument2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接