登录发现更多内容
首页
分类
发帖
账号
自动登录
找回密码
密码
登录
立即注册
立即登录
立即注册
其他登录
QQ
微信
首页
Portal
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
产品教程
BBS
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
开发资料
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
样品购买
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
IoT云平台
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
GitHub
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
技术博客
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
搜索
搜索
热搜:
LoRa
ESP8266
安信可
本版
帖子
用户
请
登录
后使用快捷导航
没有账号?
立即注册
每日签到
任务
广播
导读
排行榜
设置
我的收藏
退出
6
1
0
首页
技术杂谈
›
gdb使用总结(中)
返回列表
gdb使用总结(中)
[ 复制链接 ]
发布帖子
可乐klelee
金牌会员
9
主题
24
回帖
1473
积分
金牌会员
金牌会员, 积分 1473, 距离下一级还需 1527 积分
金牌会员, 积分 1473, 距离下一级还需 1527 积分
积分
1473
私信
6人留言
楼主
技术杂谈
1238
6
2023-9-7 20:52:51
gdb断点是调试的重要手段,常用的断点有一段断点(break),观察断点(watch)、捕捉断点(catch)和条件断点(condition)。除了这些断点之外,还有单步调试等手段常用来做调试。 ## gdb设置断点-高级应用 在上一节中有提到简单的断点设置方法,即直接通过`break number` 设置断点! 本节将在此基础上深入研究。 同样的还是基于一段简单的程序进行学习! ```c #include
int main(int argc,char* argv[]) { int num = 1; while(num<100) { num *= 2; } printf("num=%d",num); return 0; } ``` 并编译成可调试的可执行程序:`gcc -g main.c -o main.out` ) 通过main.out 进入gdb调试器 ) ### break常用命令 ```bash (gdb) break location // 在location位置暂停运行 (gdb) break location if
// 如果条件成立, 在location位置暂停运行 ``` 上述location参数列表如下: | location 的值 | 含 义 | | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | linenum | linenum 是一个整数,表示要打断点处代码的行号。要知道,程序中各行代码都有对应的行号,可通过执行 l(小写的 L)命令看到。 | | filename:linenum | filename 表示源程序文件名;linenum 为整数,表示具体行数。整体的意思是在指令文件 filename 中的第 linenum 行打断点。 | | + offset - offset | offset 为整数(假设值为 2),+offset 表示以当前程序暂停位置(例如第 4 行)为准,向后数 offset 行处(第 6 行)打断点;-offset 表示以当前程序暂停位置为准,向前数 offset 行处(第 2 行)打断点。 | | function | function 表示程序中包含的函数的函数名,即 break 命令会在该函数内部的开头位置打断点,程序会执行到该函数第一行代码处暂停。 | | filename:function | filename 表示远程文件名;function 表示程序中函数的函数名。整体的意思是在指定文件 filename 中 function 函数的开头位置打断点。 | 接下来看看实际的使用: 调试的时候首先用list看看程序的源代码,一来可以判断file有没有加载进来,而来可以了解整体程序结构: ``` (gdb) list 1 #include
2 int main(int argc,char* argv[]) 3 { 4 int num = 1; 5 while(num<100) 6 { 7 num *= 2; 8 } 9 printf("num=%d",num); 10 return 0; (gdb) ``` 然后通过打断点查看程序运行状态 ```bash (gdb) break 4 <---- 在第四行设置断点 Breakpoint 1 at 0x1144: file main.c, line 4. (gdb) run <---- 开始运行,在第一个断点处停止 Starting program: /root/c/c.biancheng.com/gdb_demo/break_demo/main.out Breakpoint 1, main (argc=1, argv=0x7fffffffeb68) at main.c:4 4 int num = 1; (gdb) break +1 <---- 在当前断点的基础上+1 设置断点(4+1) Breakpoint 2 at 0x55555555514b: file main.c, line 5. (gdb) continue <---- 继续运行,下一个断点停止 Continuing. Breakpoint 2, main (argc=1, argv=0x7fffffffeb68) at main.c:5 5 while(num<100) (gdb) break 7 if num > 10 <---- 当num大于10 的时候在第7行设置断点 Breakpoint 3 at 0x55555555514d: file main.c, line 7. (gdb) continue <---- 继续运行,下一个断点停止 Continuing. Breakpoint 3, main (argc=1, argv=0x7fffffffeb68) at main.c:7 7 num *= 2; (gdb) print num <---- 打印此时num的值,确实大于10了 $1 = 16 (gdb) ``` ### gdb tbreak命令 tbreak命令是对break命令的封装,与break命令不同的是,tbreak打出的断点是一次性的,也就是暂停运行一次后,此断点消失,这个断点常用在循环中。来看看使用: 基于上面`break 7 if num > 10` 的断点继续看,我们先在此基础上continue,继续运行看看: ``` (gdb) break 7 if num > 10 Breakpoint 3 at 0x55555555514d: file main.c, line 7. (gdb) continue Continuing. Breakpoint 3, main (argc=1, argv=0x7fffffffeb68) at main.c:7 7 num *= 2; (gdb) print num $3 = 16 (gdb) continue <---- 在上面实验的基础上continue,继续运行 Continuing. Breakpoint 3, main (argc=1, argv=0x7fffffffeb68) at main.c:7 7 num *= 2; <---- 断点停止 (gdb) print num <---- 打印num的值 $4 = 32 (gdb) ``` 然后我们同样的情况使用tbreak 打个断点看看 ``` (gdb) tbreak 7 if num > 10 <---- 使用tbreak Temporary breakpoint 1 at 0x114d: file main.c, line 7. (gdb) run Starting program: /root/c/c.biancheng.com/gdb_demo/break_demo/main.out Temporary breakpoint 1, main (argc=1, argv=0x7fffffffeb68) at main.c:7 7 num *= 2; <---- 断点停止 (gdb) print num <---- 首次打印num的值 $1 = 16 (gdb) continue <---- 继续运行 Continuing. num=128[Inferior 1 (process 37219) exited normally] <---- 程序直接结束了!num的值是128 (gdb) ``` 通过上面的实验发现,tbreak打的断点只生效了一次。 ### gdb rbreak命令 rbreak命令也是基于break的封装,其作用是,只会在指定的函数处打断点,并且断点一直生效,语法格式为: `rbreak regex` regex表示正则表达式,也就是说,我们不需要精准的输入完整的函数名,只要正则能匹配就可以打断点。 很好理解,懒得写函数了! 有时候需要持续监控某一个变量的变化,这个时候打break这种断点很显然已经不合适了,所以gdb还提供了其他的方式。gdb共有三种断点方式:break(普通断点)、观察断点和捕捉断点。接下来我们看看观察断点: ## gdb设置观察断点-watch watch命令的功能是:只有当被监控变量发生变化的时候,程序才会暂停。和 watch 命令功能相似的,还有 rwatch 和 awatch 命令 - rwatch 命令:只要程序中出现读取目标变量(表达式)的值的操作,程序就会停止运行; - awatch 命令:只要程序中出现读取目标变量(表达式)的值或者改变值的操作,程序就会停止运行。 还是以之前break的程序作为例子来学习watch ``` (gdb) break 5 Breakpoint 1 at 0x114b: file main.c, line 5. (gdb) run Starting program: /root/c/c.biancheng.com/gdb_demo/break_demo/main.out Breakpoint 1, main (argc=1, argv=0x7fffffffeb68) at main.c:5 5 while(num<100) (gdb) print num $1 = 1 <---- 此时num的值是1 (gdb) watch num <---- 使用watch为num打观察断点 Hardware watchpoint 2: num (gdb) continue <---- 继续运行 Continuing. Hardware watchpoint 2: num Old value = 1 New value = 2 <---- num 值发生了改变 main (argc=1, argv=0x7fffffffeb68) at main.c:5 5 while(num<100) <---- 暂停了 (gdb) continue <---- 继续运行 Continuing. Hardware watchpoint 2: num Old value = 2 New value = 4 <---- num 值再次发生了改变 main (argc=1, argv=0x7fffffffeb68) at main.c:5 5 while(num<100) <---- 暂停了 (gdb) ``` 上面的实验说明,watch监控的变量值一旦发生变化,程序立刻暂停。 值得一提的是,对于使用 watch(rwatch、awatch)命令监控 C、C++ 程序中变量或者表达式的值,有以下几点需要注意: - 当监控的变量(表达式)为局部变量(表达式)时,一旦局部变量(表达式)失效,则监控操作也随即失效; - 如果监控的是一个指针变量(例如 *p),则 watch *p 和 watch p 是有区别的,前者监控的是 p 所指数据的变化情况,而后者监控的是 p 指针本身有没有改变指向; - 这 3 个监控命令还可以用于监控数组中元素值的变化情况,例如对于 a[10] 这个数组,watch a 表示只要 a 数组中存储的数据发生改变,程序就会停止执行。 ## gdb设置捕捉断点-catch 捕捉断点的作用是,监控程序中某一事件的发生,例如程序发生某种异常时、某一动态库被加载时等等,一旦目标时间发生,则程序停止执行,其语法为: ``` catch event ``` | event 事件 | 含 义 | | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | throw [exception] | 当程序中抛出 exception 指定类型异常时,程序停止执行。如果不指定异常类型(即省略 exception),则表示只要程序发生异常,程序就停止执行。 | | catch [exception] | 当程序中捕获到 exception 异常时,程序停止执行。exception 参数也可以省略,表示无论程序中捕获到哪种异常,程序都暂停执行。 | | load [regexp] unload [regexp] | 其中,regexp 表示目标动态库的名称,load 命令表示当 regexp 动态库加载时程序停止执行;unload 命令表示当 regexp 动态库被卸载时,程序暂停执行。regexp 参数也可以省略,此时只要程序中某一动态库被加载或卸载,程序就会暂停执行。 | 注意,当前 GDB 调试器对监控 C++ 程序中异常的支持还有待完善,使用 catch 命令时,有以下几点需要说明: 1. 对于使用 catch 监控指定的 event 事件,其匹配过程需要借助 libstdc++ 库中的一些 SDT 探针,而这些探针最早出现在 GCC 4.8 版本中。也就是说,想使用 catch 监控指定类型的 event 事件,系统中 GCC 编译器的版本最低为 4.8,但即便如此,catch 命令是否能正常发挥作用,还可能受到系统中其它因素的影响。 2. 当 catch 命令捕获到指定的 event 事件时,程序暂停执行的位置往往位于某个系统库(例如 libstdc++)中。这种情况下,通过执行 up 命令,即可返回发生 event 事件的源代码处。 3. catch 无法捕获以交互方式引发的异常。 如同 break 命令和 tbreak 命令的关系一样(前者的断点是永久的,后者是一次性的),catch 命令也有另一个版本,即 tcatch 命令。tcatch 命令和 catch 命令的用法完全相同,唯一不同之处在于,对于目标事件,catch 命令的监控是永久的,而 tcatch 命令只监控一次,也就是说,只有目标时间第一次触发时,tcath 命令才会捕获并使程序暂停,之后将失效。 使用下面这个程序看看catch的使用: ```cpp #include
using namespace std; int main(){ int num = 1; while(num <= 5){ try{ throw 100; }catch(int e){ num++; cout << "next" << endl; } } cout << "over" << endl; return 0; } ``` ``` // 编译 g++ -g main.cpp -o main.out ``` ``` root@klelee:~/c/c.biancheng.com/gdb_demo/catch_demo# gdb main.out -q Reading symbols from main.out... (gdb) catch throw int <---- 指定捕获“throw int”事件 Catchpoint 1 (throw) (gdb) run <---- 开始运行 Starting program: /root/c/c.biancheng.com/gdb_demo/catch_demo/main.out Catchpoint 1 (exception thrown), 0x00007ffff7e98c2e in __cxa_throw () from /lib/x86_64-linux-gnu/libstdc++.so.6 <---- 异常停止 (gdb) up <---- 查看上一条执行的代码 #1 0x00005555555551ef in main () at main.cpp:7 7 throw 100; (gdb) continue <---- 继续执行 Continuing. next Catchpoint 1 (exception thrown), 0x00007ffff7e98c2e in __cxa_throw () from /lib/x86_64-linux-gnu/libstdc++.so.6 <---- 异常停止 (gdb) up <---- 查看上一条执行的代码 #1 0x00005555555551ef in main () at main.cpp:7 7 throw 100; (gdb) ``` 如上所示,借助 catch 命令设置了一个捕获断点,该断点用于监控 throw int 事件,只要发生程序就会暂停执行。由此当程序执行时,其会暂停至 libstdc++ 库中的某个位置,借助 up 指令我们可以得知该异常发生在源代码文件中的位置。 同理,我们也可以监控 main.cpp 程序中发生的 catch event 事件: ``` (gdb) catch catch int Catchpoint 1 (catch) (gdb) r Starting program: ~/demo/main.exe Catchpoint 1 (exception caught), 0x00007ffff7e804d3 in __cxa_begin_catch () from /lib/x86_64-linux-gnu/libstdc++.so.6 (gdb) up \#1 0x00005555555552d0 in main () at main.cpp:9 9 }catch(int e){ (gdb) c Continuing. next Catchpoint 1 (exception caught), 0x00007ffff7e804d3 in __cxa_begin_catch () from /lib/x86_64-linux-gnu/libstdc++.so.6 (gdb) up \#1 0x00005555555552d0 in main () at main.cpp:9 9 }catch(int e){ (gdb) ``` <留坑,准备写load选项> ## gdb设置条件断点 条件断点在之前的break 断点中已经接触过了,就是当条件触发的时候在指定位置设置断点。现在要讲的是,给指定的断点设置条件。语法如下: ``` (gdb) condition bnum expression (gdb) condition bnum ``` 参数 bnum 用于代指目标断点的编号;参数 expression 表示为断点添加或修改的条件表达式。 以下列程序为例来看看具体的使用方式: ```c #include
int main () { unsigned long long int n, sum; n = 1; sum = 0; while (n <= 100) { sum = sum + n; n = n + 1; } return 0; } ``` 对上面的程序进行编译调试,如下: ``` (gdb) list 4 unsigned long long int n, sum; 5 n = 1; 6 sum = 0; 7 while (n <= 100) 8 { 9 sum = sum + n; 10 n = n + 1; 11 } 12 return 0; 13 } (gdb) break 9 if sum=10 <---- 如果sum等于10,在第9行暂停运行 Note: breakpoint 1 also set at pc 0x55555555513b. Breakpoint 2 at 0x55555555513b: file main.c, line 9. (gdb) run <---- 开始运行,第一个断点处暂停 The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/klelee/github/c/c.biancheng.com/gdb_demo/main.out [Thread debugging using libthread_db enabled] Using host libthread_db library "/usr/lib/libthread_db.so.1". Breakpoint 1, main () at main.c:9 9 sum = sum + n; <---- 暂停了 (gdb) print sum <---- 打印sum的值,确认是我们设置的 $2 = 10 (gdb) info break <---- 查看当前存在的断点 Num Type Disp Enb Address What 1 breakpoint keep y 0x000055555555513b in main at main.c:9 stop only if sum = 1 breakpoint already hit 1 time 2 breakpoint keep y 0x000055555555513b in main at main.c:9 stop only if sum=10 breakpoint already hit 1 time (gdb) condition 2 sum=21 <---- 我们将第二个断点的条件改成sum=21 (gdb) continue <---- 继续运行 Continuing. Breakpoint 1, main () at main.c:9 9 sum = sum + n; <---- 暂停了 (gdb) print sum <---- 打印sum的值,确认是我们设置的 $3 = 21 (gdb) ``` 以上就是condition命令的一个使用方法。 ## gdb单步调试程序 GDB 调试器共提供了 3 种可实现单步调试程序的方法,即使用 next、step 和 until 命令。换句话说,这 3 个命令都可以控制 GDB 调试器每次仅执行 1 行代码,但除此之外,它们各自还有不同的功能。 用下面的例子来学习单步调试: ```c #include
int print(int num){ int ret = num * num; return ret; } int myfunc(int num){ int i = 1; int sum = 0; while(i <= num){ sum += print(i); i++; } return sum; } int main(){ int num =0; scanf("%d", &num); int result = myfunc(num); printf("%d", result); return 0; } ``` ### next命令 特点是对于函数,next只是会把它当成一行指令。来看看具体使用吧: ``` (gdb) list 1 #include
2 int print(int num){ 3 int ret = num * num; 4 return ret; 5 } 6 int myfunc(int num){ 7 int i = 1; 8 int sum = 0; 9 while(i <= num){ 10 sum += print(i); (gdb) 11 i++; 12 } 13 return sum; 14 } 15 int main(){ 16 int num =0; 17 scanf("%d", &num); 18 int result = myfunc(num); 19 printf("%d", result); 20 return 0; (gdb) 21 } (gdb) Line number 22 out of range; main.c has 21 lines. (gdb) break 16 <---- 在16行打一个普通断点 Breakpoint 1 at 0x11be: file main.c, line 16. (gdb) run Starting program: /home/klelee/github/c/c.biancheng.com/gdb_demo/step_demo/main.out ... Breakpoint 1, main () at main.c:16 16 int num =0; <---- 在此处停止 (gdb) next <---- 下一步是一个scanf语句,我们看一下next之后的效果 17 scanf("%d", &num); <---- next之后并没有让我们输入,也就是说下一步,但不执行 (gdb) next <---- 继续next 3 <---- 这里响应scanf了 18 int result = myfunc(num); (gdb) next 19 printf("%d", result); (gdb) next <---- 这个next直接到return语句,表明next不会进入到print函数内部去单步调试 20 return 0; (gdb) ``` 从上面的例子可以看出来next语句,会把函数当成一个语句,一次性执行! ### step命令 step 命令所执行的代码行中包含函数时,会进入该函数内部,并在函数第一行代码处停止执行。 ### until命令 until 命令可以简写为 u 命令,有 2 种语法格式,如下所示: ``` (gdb) until (gdb) until location ``` 其中,参数 location 为某一行代码的行号。 不带参数的 until 命令,可以使 GDB 调试器快速运行完当前的循环体,并运行至循环体外停止。注意,until 命令并非任何情况下都会发挥这个作用,只有当执行至循环体尾部(最后一行代码)时,until 命令才会发生此作用;反之,until 命令和 next 命令的功能一样,只是单步执行程序。 ## 断点禁用和删除 在程序调试过程中使用break打出来的断点,我们之前说到是永久有效的。假如说在某个程序的循环结构中打的断点,我们不需要了,那就需要考虑进行删除操作,或者禁用掉。 在删除或禁用之前需要先查看当前程序中有的断点。 ### info命令查看断点 ``` (gdb) list 2 int print(int num){ 3 int ret = num * num; 4 return ret; 5 } 6 int myfunc(int num){ 7 int i = 1; 8 int sum = 0; 9 while(i <= num){ 10 sum += print(i); 11 i++; (gdb) 12 } 13 return sum; 14 } 15 int main(){ 16 int num =0; 17 scanf("%d", &num); 18 int result = myfunc(num); 19 printf("%d", result); 20 return 0; 21 } (gdb) break 11 <---- 打第一个断点 Breakpoint 1 at 0x1182: file main.c, line 11. <---- 断点类型为:breakpoint 编号为1 (gdb) break 16 Breakpoint 2 at 0x119b: file main.c, line 16. <---- 断点类型为:breakpoint 编号为2 (gdb) run Starting program: /root/c/c.biancheng.com/gdb_demo/main.out Breakpoint 2, main () at main.c:16 16 int num =0; (gdb) continue Continuing. 3 Breakpoint 1, myfunc (num=3) at main.c:11 11 i++; (gdb) continue Continuing. Breakpoint 1, myfunc (num=3) at main.c:11 11 i++; (gdb) info break <---- 查看现在存在的断点 Num Type Disp Enb Address What 1 breakpoint keep y 0x0000555555555182 in myfunc at main.c:11 breakpoint already hit 2 times 2 breakpoint keep y 0x000055555555519b in main at main.c:16 breakpoint already hit 1 time (gdb) ``` 可能当我们了解当前阶段的运行状态之后需要删除某些断点,或者断点行数设置错误,就需要删除一些断点了。删除断点通常有两种方法,分别是clear命令和delete命令。 ### 删除断点命令——clear和delete - clear:删除指定点的所有断点 - delete:删除所有断点,或指定点的断点 ``` (gdb) info break Num Type Disp Enb Address What 1 breakpoint keep y 0x0000555555555182 in myfunc at main.c:11 breakpoint already hit 3 times 2 breakpoint keep y 0x000055555555519b in main at main.c:16 breakpoint already hit 1 time (gdb) delete 2 <---- 删除断点编号为2的断点 (gdb) info break Num Type Disp Enb Address What 1 breakpoint keep y 0x0000555555555182 in myfunc at main.c:11 breakpoint already hit 3 times (gdb) clear 11 <---- 删除在第11行的所有断点 Deleted breakpoint 1 (gdb) ``` ### 禁用断点命令——disable 禁用和删除的区别就在于断点还在不在。其常用语法为: ``` (gdb) disable # 禁用所有断点 (gdb) disable num1 num2 ... # 禁用指定的断点 ``` 如下: ``` (gdb) list 14 } 15 int main(){ 16 int num =0; 17 scanf("%d", &num); 18 int result = myfunc(num); 19 printf("%d", result); 20 return 0; 21 } (gdb) Line number 22 out of range; main.c has 21 lines. (gdb) break 16 <---- 设置一个普通断点 Breakpoint 3 at 0x55555555519b: file main.c, line 16. (gdb) run The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /root/c/c.biancheng.com/gdb_demo/main.out Breakpoint 3, main () at main.c:16 16 int num =0; (gdb) watch num <---- 设置一个观察断点 Hardware watchpoint 4: num (gdb) info break <---- 查看所有断点 Num Type Disp Enb Address What 3 breakpoint keep y 0x000055555555519b in main at main.c:16 <---- 此时断点状态为y breakpoint already hit 1 time 4 hw watchpoint keep y num (gdb) disable 3 <---- 禁用第三个断点 (gdb) info break Num Type Disp Enb Address What 3 breakpoint keep n 0x000055555555519b in main at main.c:16 <---- 断点还在,只是状态为n breakpoint already hit 1 time 4 hw watchpoint keep y num (gdb) ``` ### 打开已禁用的断点——enable 既然禁用断点让其保存,那就要有重新使用的方法,那就是enable,其语法也和disable相对应 ``` (gdb) disable (gdb) info break Num Type Disp Enb Address What 3 breakpoint keep n 0x000055555555519b in main at main.c:16 breakpoint already hit 1 time 4 hw watchpoint keep n num (gdb) enable (gdb) info break Num Type Disp Enb Address What 3 breakpoint keep y 0x000055555555519b in main at main.c:16 breakpoint already hit 1 time 4 hw watchpoint keep y num (gdb) disable 4 (gdb) info break Num Type Disp Enb Address What 3 breakpoint keep y 0x000055555555519b in main at main.c:16 breakpoint already hit 1 time 4 hw watchpoint keep n num (gdb) enable 4 (gdb) info break Num Type Disp Enb Address What 3 breakpoint keep y 0x000055555555519b in main at main.c:16 breakpoint already hit 1 time 4 hw watchpoint keep y num (gdb) ```
点赞
1
收藏
0
淘帖
0
────
1
人觉得很赞
────
回复
使用道具
举报
6 回复
电梯直达
正序浏览
倒序浏览
正序浏览
沙发
可乐klelee
楼主
回复
使用道具
举报
2023-9-7 20:54:26
随便写写第二天
回复
评论
使用道具
举报
板凳
ai_mcu
回复
使用道具
举报
2023-9-7 21:11:40
抢个板凳
回复
评论
使用道具
举报
明天总会更好
地板
ai_mcu
回复
使用道具
举报
2023-9-7 21:13:11
可乐klelee 发表于 2023-9-7 20:54
随便写写第二天
有一说一,你这随便写写含金量不少
回复
评论
使用道具
举报
明天总会更好
5
#
爱笑
来自手机
回复
使用道具
举报
2023-9-7 21:35:03
地板!
回复
评论
使用道具
举报
用心做好保姆工作
6
#
干簧管
回复
使用道具
举报
2023-11-24 19:04:33
顶
回复
评论
使用道具
举报
7
#
干簧管
回复
使用道具
举报
2023-11-25 19:12:15
赞
回复
评论
使用道具
举报
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
立即登录
手机登录
点评
高级模式
本版积分规则
回帖并转播
回帖后跳转到最后一页
返回
今日推荐
Ai-M61-32SU 模块硬件版本 V1.2-A1
浅尝bouffalo_sdk
腾讯WorkBuddy 编程测试
Codex的单片机写代码测试结果
记录下 ai编程cursor
Ai-M62-M10L的学习与使用
BU04 INIT FAILED
Ai-M61-32S-Kit学习与使用
BW16二次开发烧录失败
MDK5.40编译PB-03 SDK
热帖排行
Ai-M61-32SU 模块硬件版本 V1.2-A1
求助
立创直播还想要 “九章”MCP 验证套件的看这里
智能网球避震器,希望能与感兴趣的朋友交流
浅尝bouffalo_sdk
Ai-M61-32S开发环境搭建+电气工程及其自动化
腾讯WorkBuddy 编程测试
Codex的单片机写代码测试结果
统计信息
会员数: 30911 个
话题数: 44872 篇
首页
分类
我的