Linux下gdb attach的使用(调试已在运行的进程)

在Linux上,执行有多线程的程序时,当程序执行退出操作时有时会遇到卡死现象,如果程序模块多,代码量大,很难快速定位,此时可试试gdb attach方法。

测试代码main.cpp如下,这里为了使程序退出时产生卡死现象,在第51行时push线程sleep 100分钟:

#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;
}

build.sh脚本内容如下:

g++ -g -std=c++11 -o main main.cpp -lpthread
./main

执行:$ ./build.sh ,执行结果如下,程序无法正常退出,产生卡死现象:

通过命令:$ ps -aux | grep main ,获取执行main的进程(pid),如下图所示,执行main的进程为18786:

启动gdb attach,执行gdb attach pid即可调试正在运行的程序,执行:$ gdb attach 18786,若执行gdb attach时提示:” ptrace: Operation not permitted”,则执行:$ sudo gdb attach 18786,如下图所示:

也可执行:$ 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));语句上,分析完成,了解了程序卡死的原因,执行结果如下图所示:

GitHubhttps://github.com/fengbingchun/Messy_Test

发布了718 篇原创文章 · 获赞 1131 · 访问量 609万+

猜你喜欢

转载自blog.csdn.net/fengbingchun/article/details/99417062