1.前言
之前一直使用gdb filename方式启动调试,昨天想停住某个特定线程,然后就犯难了,捣鼓了很久。后来就想着,反正都捣鼓gdb,干脆就顺便好好研究一下attach启动方式吧。捣鼓明白之后,感觉自己太智障了,想要在non-stop下停住特定线程,使用attach才是正解。
2.attach启动方式相关
启动方式
假设:
- 程序是使用-g选项编译的,带有调试信息。
如何确认程序是否可调试?
对于没有调试信息的程序如何处理?
这类的问题在后面会介绍,先不涉及; - 默认为non-stop模式,不过all-stop模式在操作上好像也没
使用attach的话,进程id是必须,所以首先应利用以下命令找出进程id:
ps -ef | grep programName
- gdb attach pid,直接读取~/.gdbinit启动gdb,并attach到pid进程号的进程中。这里有一个缺点,如果 ~/.gdbinit中的设置并不是本次调试想要的,那么就达不到目的,因为直接启动之后就自动attach到进程了,类似non-stop之类的选项是无法在attach之后修改的;
- 在gdb内部attach启动方式,
# 和上面的差别,就是你调整某些选项,然后再attach到进程。
# 例如吧,set non-stop off。
gdb
(gdb) set some thing
(gdb) file filename
(gdb) attach pid
- gdb filename pid(–pid pid),效果和直接attach暂时来看是相同的,我的理解是这样的,因为实际运行的程序,基本上是不会保留调试信息(也就是不会带-g、-ggdb编译)。这时候怎么办呢?
我们可以另外编译一份带调试信息的啊,然后通过gdb filename pid的方式,就可以正常调试了。 这是我认为的,这种启动方式的存在意义。
# 当然,也可以这样启动,
# 区别的话,上面也说了,这样弄可以先改一改一些选项,
# 然后再attach。
gdb
(gdb) set some thing
(gdb) file filename
(gdb) attach pid
attach方式的适用场景
转载了一个stackoverflow上关于gdb attach的回答,里面提到了两种gdb attach的适用场景,或者说如果某些程序不适合适用attach方式的话,如何将其进行改造使之适用。
-
If the program to debug (in gdb lingo, “the inferior”) is long-running – for example, a GUI or a server of some kind – then the simplest way is to just run the script, wait for the inferior to start, and then attach to it. You can attach using the PID, either with gdb -p PID or using attach PID at the gdb prompt.
意思就是,那些会跑很久,甚至一直跑的程序,那是最简单的。直接让它跑起来,然后attach就行了(为什么出现script字眼?原问题提问者是因为程序的启动脚本过于复杂,才会选用attach方式进行调试的); -
If the program is short-lived, then another classic approach is to add a call to sleep early in the program’s startup; say as the first line of main. Then, continue with the attach plan.
意思就是,那些跑一会就停,可能你都还没attach到就结束的程序,如果想用attach方式调试的话,你需要修改一下源码,让它sleep一会。然后在它sleep的时候趁机attach进去,也就是夜袭(正经脸);