gdb调试

  • GDB的重要性
  • 启动gdb
  • 查看程序的源码
  • gdb启动程序
  • 设置断点
  • 删除断点或者或者禁用断点
  • 单步调式
  • 查看这个变量的值
  • gdb 调试core文件
  • 使用gdb调试正在运行的程序
  • gdb 调试多线程
  • 总结

GDB的重要性

GDB作为这个调试的利器,是非常值得我们去深入学习的。当我们的程序出现这个语法错误我们可以通过这个编译器的保存进行解决但是如果出现了逻辑错误,我们用肉眼是很难看出来。此时调试工具就排上用场了。实际场景中解决逻辑错误最高效的方法,就是借助调试工具对程序进行调试。
所谓调试(Debug),就是让代码一步一步慢慢执行,跟踪程序的运行过程。比如,可以让程序停在某个地方,查看当前所有变量的值,或者内存中的数据;也可以让程序一次只执行一条或者几条语句,看看程序到底执行了哪些代码。也就是说,通过调试程序,我们可以监控程序执行的每一个细节,包括变量的值、函数的调用过程、内存中数据、线程的调度等,从而发现隐藏的错误或者低效的代码。
各位老铁可以查看自己的机器上是否有gdb。如果没有的话,如果是再centos这个云服务器上可以使用下面这条命令进行安装

yum -y install gdb

启动gdb

首先我们需要知道程序的发布方式有两种,debug模式和release模式。Linux gcc/g++出来的二进制程序,默认是release模式要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项
首先我们再编译成员的时候需要使用-g选项,下面博主以目录下的这个文件为例子演示一下

 g++ mytest.cc -o mytest -g

启动gdb的命令如下,在这里我们的可执行程序是mytest。各位老铁记得用自己的可执行程序

  gdb mytestgdb -q mytest表示不打印gdb版本信息,界面较为干净;

测试结果如下:

[ksy@VM-4-17-centos scripts]$ clear
[ksy@VM-4-17-centos scripts]$ gdb mytest
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/>...
Reading symbols from /home/ksy/scripts/mytest...done.
(gdb) 

而这个gdb -q mytest就不会打印这些调试信息看起来就比较舒服

[ksy@VM-4-17-centos scripts]$ clear
[ksy@VM-4-17-centos scripts]$ gdb -q mytest
Reading symbols from /home/ksy/scripts/mytest...done.
(gdb)

查看程序的源码

在命令行的情况下,我们调试肯定是需要看这个源码的,如果查看源码了?我们可以使用这个
list指令,简写成l.下面我们来演示一下如何查看这个源码,首先启动gdb上面已经说过了老铁可以看看在这里我就直接启动了。

(gdb)
Line number 19 out of range; mytest.cc has 18 lines.
(gdb) quit
[ksy@VM-4-17-centos scripts]$ clear
[ksy@VM-4-17-centos scripts]$ gdb -q mytest
Reading symbols from /home/ksy/scripts/mytest...done.
(gdb) l
4   {5     int sum=0;
6     for(int i=0;i<=top;i++){7        sum+=i;
8     }
9     return sum;
10  }
11  int main()
12  {13    int top=100;
(gdb)
14    int result=SumToTop(top);
15    cout<<"结果是"<<result<<endl;
16    return 0;
17
18  }
(gdb) 

这个gdb默认可能只显示几行,并没有全部显示出来,我们可以敲回车让其把源码全部显示出来。同时我们也发现了这个并不是从第一行开始的如果我们想要从第一行开始查看我们可以使用 list n

[ksy@VM-4-17-centos scripts]$ gdb -q mytest
Reading symbols from /home/ksy/scripts/mytest...done.
(gdb) l 0
1   #include<iostream>
2   using namespace std;
3   int SumToTop(int top)
4   {5     int sum=0;
6     for(int i=0;i<=top;i++){7        sum+=i;
8     }
9     return sum;
10  }
(gdb)
11  int main()
12  {13    int top=100;
14    int result=SumToTop(top);
15    cout<<"结果是"<<result<<endl;
16    return 0;
17
18  }
(gdb) 

此时我们就可以把代码全部看到了,非常的舒服虽然没有Windows上图形化界面那么舒服。

gdb启动程序

在gdb 当中运行程序我们可以使用这个 run(简写成r)运行程序。运行程序直到遇到 结束或者遇到断点等待下一个命令。在这里博主写把博主的测试代码拿出来给大家看看。

#include<iostream>
using namespace std;
int SumToTop(int top)
{int sum=0;for(int i=0;i<=top;i++){sum+=i;}return sum;
}
int main()
{int top=100;int result=SumToTop(top);cout<<"结果是"<<result<<endl;return 0;}

下面来演示一下如何运行

[ksy@VM-4-17-centos scripts]$ gdb -q mytest
Reading symbols from /home/ksy/scripts/mytest...done.
(gdb) run
Starting program: /home/ksy/scripts/mytest
结果是5050
[Inferior 1 (process 31476) exited normally]
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64 libgcc-4.8.5-44.el7.x86_64
(gdb) 

此时由于我们没有设置这个断点所以这个他就直接跑完了。直接就拿到了结果了。

设置断点

在Linux下我们可以使用break (简写b)来设置这个断点 .其格式为这个 b(简写)行号。我们也可以同info指定查看断点信息。其指令为 info breakpoints(查看所有断点信息)或者简写为info b 下面我们来演示一下如何设置断点

[ksy@VM-4-17-centos scripts]$ gdb -q mytest
Reading symbols from /home/ksy/scripts/mytest...done.
(gdb) l 0
1   #include<iostream>
2   using namespace std;
3   int SumToTop(int top)
4   {5     int sum=0;
6     for(int i=0;i<=top;i++){7        sum+=i;
8     }
9     return sum;
10  }
(gdb)
11  int main()
12  {13    int top=100;
14    int result=SumToTop(top);
15    cout<<"结果是"<<result<<endl;
16    return 0;
17
18  }
(gdb) b 13
Breakpoint 1 at 0x40082d: file mytest.cc, line 13.
(gdb) b 15
Breakpoint 2 at 0x400841: file mytest.cc, line 15.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040082d in main() at mytest.cc:13
2       breakpoint     keep y   0x0000000000400841 in main() at mytest.cc:15
(gdb) 

在上面我们打了两个断点,我们通过了info b查看了这个断点的信息,下面我们来解释一下这些断点的信息。

  • Num: 断点编号
  • Address:内存地址
  • What:位置
  • Disp:断点执行一次之后是否有效 kep:有效 dis:无效
  • Enb: 当前断点是否有效 y:有效 n:无效

删除断点或者或者禁用断点

在上面我们已经学习到了如何打断点,下面我们来学习一些如何删除或者禁用断点。我们可以使用找个 delete breakpoints或者我们简写为 d 加断点编号。下面我们来演示一下

(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040082d in main() at mytest.cc:13
2       breakpoint     keep y   0x0000000000400841 in main() at mytest.cc:15
(gdb) d 2
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040082d in main() at mytest.cc:13
(gdb) 

那如果我们不想删掉某个断点只是想暂时禁用它。我们只是想要暂时禁用它而已我们可以使用 disable 断点编号。同意的我们想要恢复采用的是eabale 断点编号

(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040082d in main() at mytest.cc:13
(gdb) disable 1
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep n   0x000000000040082d in main() at mytest.cc:13
(gdb) enable 1
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040082d in main() at mytest.cc:13
(gdb)
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040082d in main() at mytest.cc:13
(gdb)

单步调式

单步调试是一个非常重要的技能必须要掌握,因为我们肯定是一步一步的调试理解程序执行的过程,下面介绍一下如何进行单步调试。在gdb当中我们可以使用 step (逐语句简写为 s),next(逐过程简写为n).下面来进行演示一下

[ksy@VM-4-17-centos scripts]$ clear
[ksy@VM-4-17-centos scripts]$ gdb -q mytest
Reading symbols from /home/ksy/scripts/mytest...done.
(gdb) l 0
1   #include<iostream>
2   using namespace std;
3   int SumToTop(int top)
4   {5     int sum=0;
6     for(int i=0;i<=top;i++){7        sum+=i;
8     }
9     return sum;
10  }
(gdb)
11  int main()
12  {13    int top=100;
14    int result=SumToTop(top);
15    cout<<"结果是"<<result<<endl;
16    return 0;
17
18  }
(gdb) b 13
Breakpoint 1 at 0x40082d: file mytest.cc, line 13.
(gdb) run
Starting program: /home/ksy/scripts/mytest Breakpoint 1, main () at mytest.cc:13
13    int top=100;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64 libgcc-4.8.5-44.el7.x86_64
(gdb) s
14    int result=SumToTop(top);
(gdb) n
15    cout<<"结果是"<<result<<endl;
(gdb) n
结果是5050
16    return 0;
(gdb) 

如果我们想我们想要进入找个函数的话我们可以使用step(s)。此时如果我们进入这个函数之后我们发现我们想要跳过这个 for循环我们可以使用 until 行号就可以在一个函数内部直接执行到指定的行号。又或者我们进入到这个函数我们突然才想起来这个函数是没有问题的此时我们想要执行完这个函数此时我们可以使用finish .但是如果我们想要他不经结束还要自动往下执行到第二个断点处我们可以使用这个continue(简写c).在这里不一一演示演示一步份就可以了

[ksy@VM-4-17-centos scripts]$ gdb -q mytest
Reading symbols from /home/ksy/scripts/mytest...done.
(gdb) l 0
1   #include<iostream>
2   using namespace std;
3   int SumToTop(int top)
4   {5     int sum=0;
6     for(int i=0;i<=top;i++){7        sum+=i;
8     }
9     return sum;
10  }
(gdb)
11  int main()
12  {13    int top=100;
14    int result=SumToTop(top);
15    cout<<"结果是"<<result<<endl;
16    return 0;
17
18  }
(gdb) b 13
Breakpoint 1 at 0x40082d: file mytest.cc, line 13.
(gdb) run
Starting program: /home/ksy/scripts/mytest Breakpoint 1, main () at mytest.cc:13
13    int top=100;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64 libgcc-4.8.5-44.el7.x86_64
(gdb) s
14    int result=SumToTop(top);
(gdb) n
15    cout<<"结果是"<<result<<endl;
(gdb) n
结果是5050
16    return 0;
(gdb) q
A debugging session is active.Inferior 1 [process 8271] will be killed.Quit anyway? (y or n) y
[ksy@VM-4-17-centos scripts]$ clear
[ksy@VM-4-17-centos scripts]$ gdb -q mytest
Reading symbols from /home/ksy/scripts/mytest...done.
(gdb) l 0
1   #include<iostream>
2   using namespace std;
3   int SumToTop(int top)
4   {5     int sum=0;
6     for(int i=0;i<=top;i++){7        sum+=i;
8     }
9     return sum;
10  }
(gdb)
11  int main()
12  {13    int top=100;
14    int result=SumToTop(top);
15    cout<<"结果是"<<result<<endl;
16    return 0;
17
18  }
(gdb) b 14
Breakpoint 1 at 0x400834: file mytest.cc, line 14.
(gdb) b 15
Breakpoint 2 at 0x400841: file mytest.cc, line 15.
(gdb) run
Starting program: /home/ksy/scripts/mytest Breakpoint 1, main () at mytest.cc:14
14    int result=SumToTop(top);
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64 libgcc-4.8.5-44.el7.x86_64
(gdb) s
SumToTop (top=100) at mytest.cc:5
5     int sum=0;
(gdb) until 9
SumToTop (top=100) at mytest.cc:9
9     return sum;
(gdb) p sum
$1 = 5050
(gdb) continue
Continuing.Breakpoint 2, main () at mytest.cc:15
15    cout<<"结果是"<<result<<endl;
(gdb) 

查看这个变量的值

在gdb 当中如果我们想要查看这个变量的值我们可以使用这个 display 变量名 或者使用 print(简写为p) 变量名.(display是常显示 而这个 print是这个只显示一次。如果我们想要取消常显示可以使用这个undisplay 加编号)在这里简单的演示一下。

(gdb) b 13
Breakpoint 1 at 0x40082d: file mytest.cc, line 13.
(gdb) run
Starting program: /home/ksy/scripts/mytest Breakpoint 1, main () at mytest.cc:13
13    int top=100;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64 libgcc-4.8.5-44.el7.x86_64
(gdb) p top
$1 = 0
(gdb) display top
1: top = 0
(gdb) s
14    int result=SumToTop(top);
1: top = 100
(gdb) 

gdb 调试core文件

我们的程序在运行时如果突然挂掉了,有可能会生成这个**.core**(和信号有关铁子可以去看看我的博客).但是在我们的云服务器上默认是关闭了这个功能的。此时我们需要通过以下命令打开

ulimit -a //查看这个系统参数
ulimit -c //unlimit 把core文件设置为无限制

下面我们来将其打开

[ksy@VM-4-17-centos scripts]$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7265
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 100001
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7265
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
[ksy@VM-4-17-centos scripts]$ ulimit -c 4096
[ksy@VM-4-17-centos scripts]$ ulimit -a
core file size          (blocks, -c) 4096
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7265
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 100001
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7265
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

下面我们来编写一段代码来演示这个情况

int main()
{int*ptr=NULL;*ptr=0;//制造空指针解引用return 0;
}

下面我们编译并运行这个程序我们发现在当前路径下多了一个.core 文件

[ksy@VM-4-17-centos scripts]$ ./mytest
Segmentation fault (core dumped)
[ksy@VM-4-17-centos scripts]$ ls
core.14308  mytest  mytest.cc

程序崩溃了我们最想知道的是程序到底是那里崩溃了,这是我们最关心的下面我们通过gdb 来看出一下那么崩溃了。我们只需要使用gdb mytest core.14308既可以进行调试

[ksy@VM-4-17-centos scripts]$ gdb -q mytest core.14308
Reading symbols from /home/ksy/scripts/mytest...done.
[New LWP 14308]
Core was generated by `./mytest'.
Program terminated with signal 11, Segmentation fault.
#0  0x0000000000400627 in main () at mytest.cc:6
6     *ptr=0;//制造空指针解引用
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64 libgcc-4.8.5-44.el7.x86_64
(gdb) 

此时我们就知道程序原理是这里崩溃了,就能马上定位到这里。然后我们就可以分析自己的程序最后将问题解决了。

使用gdb调试正在运行的程序

下面我们一起来看一下如何使用gdb来调试这个正在运行的程序。下面我们来说一下,当然在这里我们需要提交准备好这个测试代码

#include<iostream>
#include<unistd.h>
using namespace std;
void func2(){for(int i=0;i<1000;i++){sleep(1);cout<<"i的值为:"<<i<<endl;}
}
void func1(){func2();
}
int main()
{func1();return 0;
}

然后我们使用g++进行编译注意需要带上-g选项因为我们需要调试。接下来我们需要知道这个进程的pid我们可以通过以下两个命令来获取

ps -u //查看当前用户的所有进程
ps - axj | grep mytest


下面我们使用这个 gdb -p pid或者ps -attach pid

此时我们发现刚才那个程序此时已经停下来了。那么此时程序执行到了那里了?我们可以使用
bt 查看这个函数调用堆栈

当然我们也可以使用n,s进行调试程序。其它的和上面的调试差不多

gdb 调试多线程

下面我们一起来看看如何调试找个多线程的找个程序,同样的我们可以提前准备下找个代码

#include<iostream>
#include<unistd.h>
#include<pthread.h>
using namespace std;
int x=0;
int y=0;
void*func1(void*arg)
{for(x=0;x<=1000;x++){cout<<"x的值为:"<<x<<endl;sleep(1);}pthread_exit(NULL);
}void*func2(void*arg)
{for(y=0;y<=1000;y++){cout<<"y的值为:"<<y<<endl;sleep(1);}pthread_exit(NULL);
}int main()
{pthread_t tid1,tid2;pthread_create(&tid1,NULL,func1,NULL);pthread_create(&tid2,NULL,func2,NULL);cout<<"主线程开始等待第一个线程"<<endl;pthread_join(tid1,NULL);cout<<"主线程开始等待第二个线程"<<endl;pthread_join(tid2,NULL);cout<<"main over"<<endl;
}

同样的我们首先将程序编译好生成可执行程序,博主在这里给出

 g++ mytest.cc -o mytest -lpthread -g

将其运行之后我们可以在另外一个窗口执行以下命令

ps -aL | grep mytest //查看轻量级线程
pstree -p 主线程id //查看主线程和新线程关系


下面我们来调试他

首先我们将断点打好,并查看断点对应信息。然在run

我们可以使用info threads 查看这个轻量级线程注意前面有*号的代表正在调试这个线程

我们发现这个打印完全是乱的。当然我们可以使用 thread 加编号切分调试的线程·这样打印非常的乱。我们可以使用


这样乱打印非常的难受,我们可以通过

set scheduler-locking on//只允许当前线程其他线程全部挂起
set scheduler -locking off //让其他程序继续跑起来


此时我们发现只打印y了因为其他线程被挂起来了。

总结

run:简记为 r ,其作用是运行程序,当遇到断点后,程序会在断点处停止运行,等待用户输入下一步的命令。
continue (简写c ):继续执行,到下一个断点处(或运行结束)
next:(简写 n),单步跟踪程序,当遇到函数调用时,也不进入此函数体;此命令同 step 的主要区别是,step 遇到用户自定义的函数,将步进到函数中去运行,而 next 则直接调用函数,不会进入到函数体内。
step (简写s):单步调试如果有函数调用,则进入函数;与命令n不同,n是不进入调用的函数的
until:当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。
until+行号: 运行至某行,不仅仅用来跳出循环
finish: 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。
call 函数(参数):调用程序中可见的函数,并传递“参数”,如:call gdb_test(55)
quit:简记为 q ,退出gdb
break n (简写b n):在第n行处设置断点
(可以带上代码路径和代码名称: b OAGUPDATE.cpp:578)
b fn1 if a>b:条件断点设置
break func(break缩写为b):在函数func()的入口处设置断点,如:break cb_button
delete 断点号n:删除第n个断点
disable 断点号n:暂停第n个断点
enable 断点号n:开启第n个断点
clear 行号n:清除第n行的断点
info b (info breakpoints) :显示当前程序的断点设置情况
delete breakpoints:清除所有断点:
list :简记为 l ,其作用就是列出程序的源代码,默认每次显示10行。
list 行号:将显示当前文件以“行号”为中心的前后10行代码,如:list 12
list 函数名:将显示“函数名”所在函数的源代码,如:list main
list :不带参数,将接着上一次 list 命令的,输出下边的内容。
print 表达式:简记为 p ,其中“表达式”可以是任何当前正在被测试程序的有效表达式,比如当前正在调试C语言的程序,那么“表达式”可以是任何C语言的有效表达式,包括数字,变量甚至是函数调用。
print a:将显示整数 a 的值
print ++a:将把 a 中的值加1,并显示出来
print name:将显示字符串 name 的值
print gdb_test(22):将以整数22作为参数调用 gdb_test() 函数
print gdb_test(a):将以变量 a 作为参数调用 gdb_test() 函数
display 表达式:在单步运行时将非常有用,使用display命令设置一个表达式后,它将在每次单步进行指令后,紧接着输出被设置的表达式及值。如: display a
watch 表达式:设置一个监视点,一旦被监视的“表达式”的值改变,gdb将强行终止正在被调试的程序。如: watch a
whatis :查询变量或函数
info function: 查询函数
扩展info locals: 显示当前堆栈页的所有变量
where/bt :当前运行的堆栈列表;
bt backtrace 显示当前调用堆栈
up/down 改变堆栈显示的深度
set args 参数:指定运行时的参数
show args:查看设置好的参数
info program: 来查看程序的是否在运行,进程号,被暂停的原因。

室友打了一晚上游戏我学会了使用GDB调试相关推荐

  1. 室友上了个厕所我就学会了递推算法解决汉诺塔hanoi

    对于游戏的玩法,我们可以简单分解为三个步骤 1)将前63个盘子从X移动到Y上: 2)将最底下的第64个盘子从X移动到Z上: 3)将Y的63个盘子移动到Z上: 第二步是最容易实现的一步,那么第一步和第三 ...

  2. 室友用一盘王者荣耀就学会了多线程

    目录 多线程创建的两种方式: 为什么要重写run方法? run()方法和start方法的区别? 通过继承的方法和实现接口的方式创建多线程,哪个好? 一.前言 线程可能听起来有点难,其实也是非常好理解的 ...

  3. 室友利用一把王者的时间就学会了【C语言结构体内存对齐】

    文章目录 一.什么是结构体内存对齐? 二.结构体的对齐规则 结构体内存对齐规则的具体应用 三.为什么会存在内存对齐 总结 提示:以下是本篇文章正文内容,下面案例可供参考 一.什么是结构体内存对齐? 从 ...

  4. 【室友用一局王者荣耀的时间学会了用python写春联】

    目录 0.效果展示 1.导入模块 2.获取对应汉字内容及像素 3.生成并保存对联 2022年了,又到了贴对联的时间了,不得安排一波用python脚本写对联吗? 0.效果展示 竖排: 横批: 1.导入模 ...

  5. 室友在宿舍玩游戏我学java_在宿舍写代码总被一个室友认为在装逼,该怎么办?...

    我也跟题主有同感,我以前学过点,以为能进地狱副本,跟室友并肩作战,建功立业, 没想到,直接被分到新手村里了. 在寝室里,我永远是起的最早,睡的最晚那位.我也是,每天都在做算法题,张口闭口二叉树,图啊, ...

  6. QQLHZ推荐日志:大学第一晚上,室友拿出的惊人物品

    1.以前我不住校,高三每天6点半骑自行车上学,23点放学骑回家,一天17个小时.放学后还不想回家,大半夜闲逛.个性日志 现在我必须住校,每年初春新秋坐火车上学,仲夏大寒卧铺回家,算一算,300天. 于 ...

  7. 阿里老P8,被大学天天打游戏的室友吊打了!

    社会就是一所与学习成绩无关的大学,学校的学历和学习只是门槛,修行靠个人,机遇相对来说也是非常重要的.这不同样一所学校毕业,同为室友,毕业后也会有很大的不同:阿里老P8,被以前的室友吊打了,今天听到同学 ...

  8. python断网还能用吗_室友打游戏时,让他断网掉线!明明没断网就是没网!Python黑客!...

    原标题:室友打游戏时,让他断网掉线!明明没断网就是没网!Python黑客! 为了满足新手对Python的追求,特写了三个初级Python入门工具.第一期写了三个初级工具,希望新手看完以后可以对Pyth ...

  9. C语言数字游戏(室友打断腿版)

    C语言数字游戏(室友打断腿版) 猜数字部分 界面实现 代码实现: 玩家选择实现 代码实现 游戏部分 随机数的生成 随机值代码实现 游戏输入和判断部分 代码部分 收尾 整体代码 舍友打断腿版 代码 尾声 ...

最新文章

  1. 中科院德州扑克AI获卓越论文奖!AAAI 2022开奖,吴恩达获纪念讲座奖
  2. VTK:vtkArrayToTable用法实战
  3. [Cocos2d-x For WP8]Menu菜单
  4. python opencv 直方图均衡_详解python OpenCV学习笔记之直方图均衡化
  5. lnmp 0.4 安装指南
  6. 读取数据库并写入excel表中 发送邮件
  7. 华硕主板无盘启动bios设置_legacy和UEFI启动是什么?电脑BIOS设置开启进入UEFI启动方法...
  8. linux下创建用户,给用户设置密码,给用户授权
  9. OC学习笔记四 数据类型
  10. vb中查询mysql_vb数据库查询语句-vb中使用sql语句-vb读取sql语句的字段
  11. cad抛物线曲线lisp_cad画缓和曲线lisp程序(1)
  12. 淘宝、天猫、京东、苏宁等平台抢购脚本
  13. 上海十大it外包公司
  14. 凑微分公式_第一换元积分法(13种常用的凑微分公式)☀成考·高数二辅导
  15. 【基于 C++ 面向 Window API 的自制工具】批量重复单键操作器
  16. C语言中的绝对值函数
  17. Qt5.9/C++架构实例(一个简单的MCV架构应用实例)
  18. C. The Intriguing Obsession(神仙组合数)
  19. 通过powerbuilder直接读和写Excel文件,支持xlsx,xls,et等格式,不需要安装office excel,WPS等依赖
  20. 中国量化金融行业 全解 金融工程 计算机 统计学 金融 专业领域 就业指南

热门文章

  1. 30w 重金等你挑战,数字合肥广邀智慧城市建设英才
  2. 敏捷软件研发思想讲解
  3. 今天我们说个一直以来的有趣话题:男程序员都是秃头,女程序员满脸痘痘
  4. java图片框_java实现图片写入高清字体及带边框的方法
  5. 87654321盏灯!
  6. Pyinstaller打包pygame包的aliens.py文件
  7. 自学软件测试,一段心路历程,这个世界根本没有速成的方法
  8. 新电脑重装系统好吗?电脑重装系统的好坏
  9. (2)RIL简析(高通)——消息处理
  10. RIL层源码分析(原)