使用GBD调试多线程

今天在公司遇到开发服务器的时候遇到一个Oracle没有第三方库的情况,然后程序直接崩溃,生成CORE文件。最后在同事的帮助下,找到问题所在,在执行设置环境变量的Shell脚本的时候,没有生成Oracle(OCCI)所使用的第三方库的文件和文件夹导致的。

虽说问题解决了,但是在平时的日常开发中更多的使用cout打印输出日志文件。

而在Linux开发过程中没有像Visual Studio的可视化的调试IDE,所以如果不想使用cout打印日志输出的话,只能使用GDB来调试程序,平时服务器开发常用到多线程。

所以今天结合多线程一个最简单的程序给大家讲讲如何使用GDB调试多线程。

需要调试的程序:

<span style="font-family:SimSun;font-size:10px;">//使用GDB调试多线程程序
#include <iostream>
#include <stack>
#include <pthread.h>
using namespace std;

stack<int> s;
int number = 0;
void* stack_pop(void *)
{
	pthread_detach(pthread_self());
	while(1)
	{
		if(!s.empty())
		{
			int top = s.top();
			s.pop();
			cout<<"stack pop number is: "<<top<<endl;
			--number;
		}
	}
}

void* stack_push(void *)
{
	pthread_detach(pthread_self());
	while(1)
	{
		s.push(number);
		cout<<"stack push number is: "<<number<<endl;
		++number;
	}
}

int main()
{
	int errorcode;
	pthread_t ti1,ti2;
	errorcode = pthread_create(&ti1, NULL, stack_pop, NULL);
	if(errorcode != 0 )
		cout<<"create stack_pop thread is failed!"<<endl;
	errorcode = pthread_create(&ti2, NULL, stack_push, NULL);
	if(errorcode != 0 )
		cout<<"create stack_push thread is falied!"<<endl;
	pthread_join(ti1, NULL);
	pthread_join(ti2, NULL);
	return 0;
}
</span>
代码中主要是就是一个Thread用于往Stack中Push数据,另一个Thread用于Pop数据。

1、使用GDB编译.cpp文件,使用pthread库

使用g++ -g选项:生成调试信息。GNU调试器可利用该信息。

2、进入GDB调试环境

使用gdb + 生成文件名称直接进入调试环境,如果成功提示Reading symbols from 可执行文件所在路径...done

3、开始调试

键入 start


start:开始执行程序并停在main函数的第一条语句处。在pthread_create处之前有pthread_t变量的声明,GDB是直接跳过的。

提示信息中说明在程序的39行有一个临时断点,接下来将执行39行代码。

键入 b + 函数名


表示在stack_pop和stack_push这两个函数的入口添加断点

键入n(Next的首字母)


n:就是平常所说的单步调试。生成一个新的线程将要执行40行代码。

键入3次回车


在GDB中使用回车是执行上一次的命令(上一次命令是单步调试),

bt表示打印当前函数信息,由于之前加入断点,程序停在代码14行处

键入多次回车


程序中stack没有数据,所以执行while(1)和if条件判断。由于在执行当前线程时,主线程也在通过CPU时间片进行调度,所以创建stack_push线程。

键入info threads命令


info threads:显示当前可进行调试所有线程。每一个线程会有GDB为其分配的ID,在后续操作中(线程间进行切换)会用到这个ID。前面的*表示的是当前所在线程,现在这个程序在stack_pop这个线程上。

键入finish和bt


bt:打印的是堆栈信息,这个信息是从栈顶到栈底的信息。调用顺序依次向下#0->#1->#2->...

finish:一直执行到当前函数返回,即跳出当前函数,执行其调用函数。所以先执行_lll_lock_wait_private()方法->_L_lock_4784()->...->clone()方法,方法后面接的是放在所在的库名。在finish之后停到断点2,也就是stack_push函数入口处。

当然可以使用f+数字,表示跳到某个栈帧的位置。这里就不演示此操作了。

键入 p i


p(print) 变量名:表示打印输出变量当前值。$1表示当前的临时变量名称是$1,因为在调试的时候有需要时,会将当前你的临时值存放起来。

键入 p 变量(stl类型变量)


会提示当前这个STL变量中有多少个元素,这里显示的是0个有元素

用命令thread ID切换到2,键入 i locals


i locals:表示打印出当前所有局部变量的值


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值