linux gdb调试及条件变量的使用总结

一) gdb的基本使用方法:
1)gdb 常用命令:

	b         b 18 如设置18行为断点
	c         continue 继续运行,如果有断点,则运行到下一个断点停止,没有的话就一直运行;
	n         执行下一条语句
	s         执行当前语句,如果是函数,则进入函数内部执行;
	p         显示变量值,如p  num;
	q         退出gdb环境;
	delete breakpoints(d b):删除所有断点
	delete breakpoints n:删除序号为n的断点
	info  b   查看断点的信息;

2)如果是多文件时,断点设置方法:b src/main.cpp:127 //多文件调试时,断点设置方法
3)g++ -g -o a.out test.c //gdb调试的时候,这个顺序不能写反了 -g -o
4)SIGSEGV: SIG 是信号名的通用前缀, SEGV 是segmentation violation,也就是存储器区段错误。
5)gdb a.out //gdb启动程序方法。
6)set args 111 222 //设置主程序的参数的方法,注意,“args"不能写成"argv”
p argv[0] //程序名称
p argv[1] //设置的111
p argv[2] //设置的222
7)ulimit -a //查看系统限制情况
ulimit -s unlimited //设置堆栈为无限制
ulimit -c unlimited //设置core dump为无限制
再次运行有问题的代码,会产生一个core文件。
在gdb调试中,bt命令 查看函数的调用栈;
(gdb) bt
#0 0x00000000004004ec in bb (bbb=13) at test.c:6
#1 0x0000000000400506 in aa (aaa=13) at test.c:10
#2 0x0000000000400522 in main (argc=1, argv=0x7ffe67963888) at test.c:15
8) 有时候core文件生成不了,原因是需要更改内核的模型文件,方法如下图所示:
在这里插入图片描述

对于(7)的案例,测试代码如下:
#include<stdio.h>
#include<errno.h>
int bb(int bbb)
{
    int *p = 0;
    *p = bbb;
}
int aa(int aaa)
{
   bb(aaa);                                                                                                                 
}
int main(int argc, char* argv[])
{
    aa(13);
    return 0;
}

对上面代码进行编译:g++ -g -o a.out test.c
之后按如 gdb a.out core 输入后,错误提示如下:

jiang@jiang-ThinkPad-X280:~/ab_project/netprogram$ gdb a.out core 
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 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-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a.out...done.

warning: exec file is newer than core file.
[New LWP 13253]
Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00000000004004ec in bb (bbb=13) at test.c:6
6		*p = bbb;  //问题出现在这里
(gdb) 

从上提示可以知道,在“6		*p = bbb;”这条语句,出现错误;

二) gdb调试正在运行的程序:
(1)查看一个运行程序的进程编号方法:

	ps -ef|grep test

终端输出结果(注意:31492是进程编号,后面的1521是进程组编号):

jiang    31492  1521  0 13:31 pts/21   00:00:00 ./test
jiang    31499  6719  0 13:31 pts/2    00:00:00 grep --color=auto test

(2)一个终端运行程序,另一个终端输入:sudo gdb test -p 32325 (必须用超级用户命令)
执行完上面的语句,则程序停止运行,如果退出gdb,则程序继续运行;
三) gdb多进程调试:
测试代码如下:

#include<stdio.h>
#include<errno.h>
#include<unistd.h>
#include<stdlib.h>
int main(int argc, char* argv[])
{
    printf("begin-------\n");
    if(fork() != 0)
    {   
        int ii; 
        printf("I parent process,pid=%d,ppid=%d\n",getpid(),getppid());
        for(ii = 0; ii < 10; ii++)
        {
            printf("ii is %d\n",ii);
            sleep(1);
        }
        exit(0);
    }   
    else    
    {   
        int jj; 
        printf("I son process,pid=%d,ppid=%d\n",getpid(),getppid());
        for(jj = 0; jj < 10; jj++)
        {
            printf("jj is %d\n",jj);
            sleep(1);
        }
        exit(0);
    }   
    return 0;
}

(1)设置进程调试模式如下,缺省调试的进程是父进程!

set follow-fork-mode child   //设在子进程为调试模式,则父进程可以运行完
set follow-fork-mode parent  //设在父进程为调试模式,子进程可以运行

(2)打开或挂起进程调试,命令如下:

set detach-on-fork [on/off] //如打开或禁止子进程运行(默认为打开状态)
//缺省为on,表示调试当前进程的时候,其他进程可以继续运行;
//如果是off,表示调试当前进程的时候,其他进程被gdb挂起;

(3)查看调试的进程: info inferiors,测试如下:

(gdb) info inferiors 
  Num  Description       Executable        
* 1    process 11261     /home/jiang/ab_project/netprogram/test  //带星号的为当前调试进程
  2    process 11299     /home/jiang/ab_project/netprogram/test 

切换当前调试的进程: inferior 进程ID (一定要注意,可不是进程号,就是前面的1或者2)
四) gdb多线程调试:

命令行编译一个多线程的命令书写格式:  g++ 2.cpp -g -o test -std=c++11 -lpthread

(1)查看轻量级的线程方法:

ps -aL|grep test

输出结果如下:

16146 16146 pts/2    00:00:00 test
16146 16147 pts/2    00:00:00 test
16146 16148 pts/2    00:00:00 test

(2)查看主线程和子线程的关系,测试方法:

pstree -p 16146 //16146问主线程id

输出结果如下:

test(16146)─┬─{test}(16147)
            └─{test}(16148)

(3)在gdb调试环境下,查看线程个数的方法:

info threads

输出结果输入:

  Id   Target Id         Frame 
  1    Thread 0x7ffff7fd0740 (LWP 19922) "test" 0x00007ffff7bc298d in pthread_join (threadid=140737336633088, thread_return=0x0) at pthread_join.c:90
  2    Thread 0x7ffff6f4e700 (LWP 19926) "test" 0x0000000000400da0 in std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)@plt ()
* 3    Thread 0x7ffff674d700 (LWP 19927) "test" fun (c=66 'B') at 2.cpp:12  //这个3为调试线程

(4)线程切换的方法:

thread 2 //2为线程Id编号

(5) gdb中,线程的其他操作:

 只运行当前线程 :  set  scheduler-locking on
 运行全部线程: set scheduler-locking off

一) 多线程中,条件变量和队列组合的使用方法:

#include<iostream>
#include<deque>
#include <thread>             // std::thread
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
using namespace std;

std::deque<int> q;
std::mutex mu; 
std::condition_variable cond;

void function_1() //生产者
{
    int count = 10; 
    while (count > 0)  
    {   
        std::unique_lock<std::mutex> locker(mu);
        q.push_front(count);
        locker.unlock();
        cond.notify_one();  // Notify one waiting thread, if there is one.
                                                                                                                                                                             
        std::this_thread::sleep_for(std::chrono::seconds(1));
        count--;
    }   
}

void function_2() //消费者
{
    int data = 0;
    while (data != 1)  
    {   
        std::unique_lock<std::mutex> locker(mu);
        while (q.empty())
            cond.wait(locker); // Unlock mu and wait to be notified
        data = q.back();
        q.pop_back();
        locker.unlock();
        std::cout << "t2 got a value from t1: " << data << std::endl;
    }   
}
int main() 
{
    std::thread t1(function_1);
    std::thread t2(function_2);
    t1.join();
    t2.join();
    return 0;
}
~    

输出结果如下:

t2 got a value from t1: 10
t2 got a value from t1: 9
t2 got a value from t1: 8
t2 got a value from t1: 7
t2 got a value from t1: 6
t2 got a value from t1: 5
t2 got a value from t1: 4
t2 got a value from t1: 3
t2 got a value from t1: 2
t2 got a value from t1: 1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值