【gdb】gdb attach
gdb attach
gdb attach
的用法:
#include <stdio.h>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <chrono>
namespace {
class Queue {
public:
Queue() = default;
~Queue() { }
void Init(int num) {
for (int i = 0; i < num; ++i) {
queue_.push(i);
}
}
int Pop() {
std::unique_lock<std::mutex> lck(mutex_);
while (queue_.size() == 0) {
cv_.wait(lck);
}
int value = queue_.front();
queue_.pop();
return value;
}
void Push(int value) {
std::unique_lock<std::mutex> lck(mutex_);
queue_.push(value);
cv_.notify_all();
}
private:
std::queue<int> queue_;
std::mutex mutex_;
std::condition_variable cv_;
}; // class Queue
bool running = false;
void push(Queue& q) {
int value = 100;
while (running) {
q.Push(value++);
std::this_thread::sleep_for(std::chrono::minutes(100));
}
}
void pop(Queue& q) {
while (running) {
fprintf(stdout, "pop value: %d\n", q.Pop());
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
} // namespace
int main()
{
fprintf(stdout, "test start\n");
Queue q;
q.Init(2);
running = true;
std::thread th1(push, std::ref(q));
std::thread th2(pop, std::ref(q));
std::this_thread::sleep_for(std::chrono::seconds(10));
running = false;
th1.join();
th2.join();
fprintf(stdout, "test end\n");
return 0;
}
[root@node01 ~]# gdb attach 875869
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
attach: No such file or directory.
Attaching to process 875869
Reading symbols from /root/test/a.out...done.
Reading symbols from /lib64/libpthread.so.0...Reading symbols from /usr/lib/debug/usr/lib64/libpthread-2.17.so.debug...done.
done.
[New LWP 875871]
[New LWP 875870]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Loaded symbols for /lib64/libpthread.so.0
Reading symbols from /lib64/libstdc++.so.6...Reading symbols from /usr/lib/debug/usr/lib64/libstdc++.so.6.0.19.debug...done.
done.
Loaded symbols for /lib64/libstdc++.so.6
Reading symbols from /lib64/libm.so.6...Reading symbols from /usr/lib/debug/usr/lib64/libm-2.17.so.debug...done.
done.
Loaded symbols for /lib64/libm.so.6
Reading symbols from /lib64/libgcc_s.so.1...Reading symbols from /usr/lib/debug/usr/lib64/libgcc_s-4.8.5-20150702.so.1.debug...done.
done.
Loaded symbols for /lib64/libgcc_s.so.1
Reading symbols from /lib64/libc.so.6...Reading symbols from /usr/lib/debug/usr/lib64/libc-2.17.so.debug...done.
done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug/usr/lib64/ld-2.17.so.debug...done.
done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00007fc09f048017 in pthread_join (threadid=140465265772288, thread_return=0x0) at pthread_join.c:90
90 lll_wait_tid (pd->tid);
(gdb)
也可执行:$ gdb main 18786,与gdb attach 18786相同。
常用的命令如下:
1. bt:查看函数调用栈的所有信息,当程序执行异常时,可通过此命令查看程序的调用过程;
2. info threads:显示当前进程中的线程;
3. thread id:切换到具体的线程id,一般切换到具体的线程后再执行bt等操作。
首先执行info threads,发现共有3个线程,当前线程id是1,即主线程,执行bt,会发现程序卡在第77行,即th1.join()语句上,即在push函数内没有退出;执行thread 2,再执行bt,发现此线程在执行pop函数,卡在了第24行的cv_.wait(lck)语句上;执行thread 3,再执行bt,发现此线程在执行push函数,卡在了第51行的std::this_thread::sleep_for(std::chrono::minutes(100));语句上,分析完成,了解了程序卡死的原因,执行结果如下图所示:
总结:
命令 | 说明 |
info threads | 显示当前进程中的线程 |
thread id | 切换到具体的线程id,一般切换到具体的线程后再执行bt等操作 |
bt | 查看函数调用栈的所有信息,当程序执行异常时,可通过此命令查看程序的调用过程 |