C/C++调试实战:用GDB快速定位崩溃、死锁与内存问题
写了几年C/C我越来越觉得调试能力和写代码能力完全是两码事。很多人写代码飞快一遇到段错误就开始瞎猜加printf、注释代码、重启程序折腾几个小时也不一定定位到问题。其实大多数崩溃、死锁、内存越界用GDB老老实实走一遍几分钟就能看到答案。这篇内容就是我自己日常用GDB的完整沉淀从编译选项到断点玩法从core dump分析到多线程死锁排查全部按实操场景来写。适合刚入门C/C调试的开发者也适合那些用了好久GDB但只会break、next、print三板斧的人。看完你应该能独立处理工作中八成以上的疑难问题。1. 调试前的准备工作编译选项与启动方式1.1 编译选项-g 不是唯一的答案很多人以为调试只要加个-g就行其实这里面细节不少。我见过不少同事在release分支上编译生产代码用-O2 -g结果调试时变量全是optimized out单步也跳得乱七八糟第一个反应就是GDB烂。真不是GDB的问题是编译选项的配合问题。先讲清楚基础。GCC加-g会生成DWARF调试信息这是GDB能映射机器指令和源码行、变量名的根本。要注意的是-g生成基础调试信息够用。-g3额外包含宏定义等扩展信息可以用info macro查看宏展开排查宏相关Bug很管用。-ggdb生成面向GDB的调试信息体积更大一般不需要。配合-O0关闭优化变量值基本都能看到单步行为符合源码顺序。配合-O2开启优化变量可能被优化掉、代码重排、函数内联调试体验会打折扣。我自己的习惯是日常开发和自测用-g -O0排查问题最快如果怀疑是优化相关Bug或者要查release崩溃那就用-g -O2编一份带调试符号的版本虽然有些变量看不了但至少崩溃栈是准的。还需要强调一点-g和优化等级并不冲突生产环境用-O2 -g编译并保留符号文件是业界非常常见的做法既不拖慢线上速度又能支撑事后分析。还有个容易踩的坑只加了-g但忘记关strip。很多构建脚本在打包阶段会执行strip删掉符号导致GDB提示No symbol table is loaded。遇到这种情况先检查二进制本身别急着怪GDB。提示如果程序用了动态库编库时也要加-g否则进库函数就只能看到汇编看不到源码和变量。我自己就吃过这个亏查了半天以为自己断点打错了。1.2 三种启动调试的方式GDB支持三种启动方式适用场景完全不同第一种直接启动未运行的程序gdb ./my_program gdb ./my_program arg1 arg2如果程序需要传很多参数或者带了环境变量可以不用在命令行写进GDB后用set args设置(gdb) set args --input /data/file.txt --verbose (gdb) set env LD_LIBRARY_PATH/opt/mylib:$LD_LIBRARY_PATH (gdb) runrun不带参数会用set args里设置的内容这点比每次敲完整命令行方便太多。第二种用core文件做崩溃后分析gdb ./my_program core.12345这种方式最大的价值在于事发现场重建。程序崩了内核把内存镜像写到core文件里GDB加载后能直接告诉你崩溃在哪个函数、当时的调用栈是什么、局部变量值是什么。注意core文件必须和同一个二进制的崩溃现场匹配最好用当时线上跑的那份二进制或完全一致的构建产物否则符号对不上栈可能全是错的。第三种附加到正在运行的进程(gdb) attach 12345进程PID可以用pidof my_program查。附加常用于线上问题、死循环、假死类问题。这里有两个硬性前提一是系统允许ptraceLinux下要检查/proc/sys/kernel/yama/ptrace_scope为1时只能attach子进程有些发行版默认就是1需要适当调整自己开发机改成0没问题二是权限要够通常需要和进程相同用户或root。很多新手不知道GDB里可以直接用gdb -p 12345等价于启动后执行attach 12345。调试完记得先detach再退出避免把人家线上进程直接杀掉。2. 断点的正确玩法从基础到条件断点2.1 基础断点的几种设置方式break命令看似简单但不同写法适用不同场景(gdb) break main # 按函数名下断点最简单 (gdb) break foo.c:42 # 按文件行号适合定位具体代码行 (gdb) break foo.c:42 if x 5 # 行号条件 (gdb) break *0x40123c # 按地址下断点汇编调试或者无符号时用 (gdb) tbreak # 临时断点命中一次后自动删除 (gdb) rbreak foo_* # 正则匹配给一批函数下断点我特别想说一下tbreak的场景。有时候你只是想快速跳过某段逻辑但不确定这段逻辑会不会被多次执行用普通断点就会反复停住。tbreak一次命中即消失非常适合我就想看一眼第一次执行到这里的状态这种需求。rbreak也是好东西。比如怀疑某个模块里所有foo_开头的函数都有问题一条命令全打上断点然后continue挨个看比自己手动下十个断点快得多。2.2 条件断点与命令组让断点自动化条件断点是排查循环类Bug的大杀器。比如一个for循环跑一万次第5234次才出错你手动按continue会按疯掉。正确做法(gdb) break loop_func (gdb) condition 1 i 5234 (gdb) run这里1是断点编号。更细的还有ignore(gdb) ignore 1 5233含义是跳过前5233次命中第5234次才停下。用ignore比大型条件表达式快因为它不需要每轮循环都执行条件判断。在极端热循环里这个性能差异还是能感觉到的。断点还可以绑定命令组命中后自动执行一串GDB命令(gdb) break foo.c:88 (gdb) commands 2 printf x%d, y%d\n, x, y bt 3 continue end这段的意思是每次命中2号断点先把x、y和栈顶三层打出来然后自动继续跑。这就是GDB版printf但比写死代码再重新编译靠谱得多。我排查线上问题时经常先来一套这种组合拳不用改代码、不用重新发布直接就观察现场。条件断点还有个容易踩的坑条件表达式里引用不存在的变量GDB不会报错而是把断点变成无条件断点每次都停。排查时如果发现断点不听话先info breakpoints看条件列是否正常再用cond重新设置。2.3 观察点 watch追踪变量的每一次变化有时候你根本不知道变量什么时候被改的只知道值不对。这时候靠断点很被动观察点watchpoint才是正解。(gdb) watch x # 写观察x 每次被改都会停 (gdb) watch -l x # 按内存地址观察解决局部变量失效问题 (gdb) rwatch x # 读观察每次读取 x 都会停 (gdb) awatch x # 读写都观察我印象最深的一次是排查一个全局配置被意外篡改的问题。那是个结构体某天运行到一半某个字段变成乱七八糟的值根本不知道谁干的。我用watch盯住那个字段第一次停下看栈发现是某个模块越界写把旁边内存覆盖了。这种问题用通读代码的方式去查没个一天下不来。观察点有两个硬约束需要记住观察点依赖硬件调试寄存器数量有限x86上一般是4个左右同时watch太多变量会报错。局部变量的观察点在函数退出后自动失效。如果变量在栈上函数返回后内存会被复用watch就无意义了。有时需要watch -l按地址观察但同样要注意地址失效问题。3. 单步调试与控制流的核心命令3.1 next、step、finish、until怎么走才是对的单步命令看着简单但很多人从没用对过next执行到当前源码行的下一行如果这行有函数调用整个函数一口气执行完不进入函数体。step执行到下一行但遇到函数调用会进入函数体在函数里逐步执行。stepi按机器指令单步进入汇编级别调试无符号代码或者看编译器生成代码时用。finish一直执行到当前函数返回然后停下来适合你已经看完函数前半段、想快速跳出时用。until执行到指定的源码行不带参数时相当于一直执行到跳出当前循环在循环里用非常顺手。return不等函数执行完直接强制返回可以指定返回值适合跳过一段已知有问题的逻辑继续往下走。我举个例子说明until的妙用。比如一个循环体1000行你看到第500行时想快速跳到循环结束按next或者continue都不合适——next会一行行走完整个循环continue会一路执行到下一个断点。这时候until不带参数GDB会一直执行到当前循环体退出一次到位。finish也有个经典用法调用一个复杂函数后返回值不对你可以用step进入函数看内部逻辑但只看了开头就想出去finish直接跑完整个函数并停在调用处返回值一目了然。3.2 print 命令的花样玩法print是调试里最高频的命令但大多数人的用法只开发了它两成功力(gdb) print x # 十进制打印 (gdb) print /x x # 十六进制排查地址和标志位必须 (gdb) print /d x # 强制十进制 (gdb) print /s p # 把指针当字符串打印 (gdb) print *arr10 # 连续打印数组前10个元素arr是指针也能用 (gdb) print arr[0] # 打印地址 (gdb) print x y # 直接算表达式甚至可以调用函数语法特别实用。你有个指针p它指向一块分配了100个int的内存直接print *p只看得到第一个元素写print *p100全部打出来。排查越界写时我经常把相邻区域也打出来对比。另外print还能调用程序里的函数比如print my_debug_helper(p)。不过有两点必须提醒一是调用的函数会真的在调试进程里执行如果函数本身有副作用或者可能崩溃会污染现场二是在没有符号时没法调用。如果每走一步都想看某个变量不用每次都敲print用display(gdb) display x (gdb) display /x *p10之后每次单步GDB会自动把这些表达式打出来和IDE里的监视窗口一样。等价的info display看已注册的表达式undisplay 编号删除。再说一下GDB的变量操作。调试时可以临时改值比如想测试某个异常分支(gdb) set x 0 (gdb) set var x 0改动之后程序继续跑就会用到新值。这个能力非常强大但也容易把自己坑了——我见过有人在调试时改坏数据导致后面一连串误判。改值前先想清楚这个变量的new值会不会被后续代码继续使用。3.3 多线程调试锁定调度与线程视图多线程程序是GDB调试里真正的重灾区。GDB默认在断点命中时会停止所有线程但你在一个线程里单步时其他线程可能还在跑这会导致你观察的状态是动态变化的非常容易误判。关键命令(gdb) info threads # 列出所有线程带编号和当前栈顶 (gdb) thread 3 # 切换到3号线程 (gdb) thread apply 2 3 bt # 对2、3号线程都执行bt (gdb) thread apply all bt # 所有线程打印调用栈死锁排查第一招 (gdb) set scheduler-locking on # 打开调度锁set scheduler-locking on是单步多线程程序时最重要的设置。它会确保你单步当前线程时其他线程全部冻结这样观察到的任何全局状态都是确定性的。排查完记得set scheduler-locking off恢复。死锁场景我一般上来就是thread apply all bt把每个线程当前栈打了看谁在等锁、锁被谁持有基本就清楚了。后面第6节我会用一个实际例子完整走一遍。另一个容易忽略的点是断点在多线程环境里可能被多个线程同时命中。如果不想在无关线程停下断点条件里可以加线程号(gdb) break foo.c:66 thread 3这个断点只在3号线程执行到该行时停下来非常省事。4. 崩溃现场重建core dump 分析全流程4.1 开启 core dump 的正确姿势Linux下core文件默认经常是关闭的。检查方式ulimit -c输出0就是关着的。临时打开ulimit -c unlimited注意这是shell的内建命令只对当前shell和它的子进程生效。想永久生效要写到/etc/security/limits.conf或者profile里但这属于环境配置不同系统差别大我只强调一点开发机随手设成unlimited不亏因为崩溃分析省下的时间远超那点磁盘。core文件往哪写由内核参数决定cat /proc/sys/kernel/core_pattern很多系统默认是core表示写到当前工作目录文件名就叫core。也有系统带管道符号比如|/usr/share/apport/apportcore会被交给外部程序处理这时你可能在当前目录找不到core需要去系统日志里看落到了哪。我自己一般会把开发机设成core.%e.%p这样文件名带了程序名和PID不容易搞混多份core。注意除了内核开关程序自身也可能通过setrlimit关闭core生成。还有当进程的工作目录不可写时core也生成不了。如果你死活等不到core文件先把这两个方向查了。4.2 从 core 文件定位段错误的核心步骤拿到core之后最经典的操作是gdb ./my_program /path/to/core进去之后第一件事GDB通常会直接显示崩溃信号和地址比如SIGSEGV。然后我固定执行两板斧(gdb) bt (gdb) frame 0bt是backtrace打出从崩溃点到main的完整调用链。frame 0切到最内层栈帧再看局部变量(gdb) info locals (gdb) print variable_name这里我要强调崩溃栈的最外层也就是frame 0是案发第一现场但变量可能已经被破坏。经常需要往上翻几帧看调用者的数据对比才能判断是调用方传了错参数还是被调方自己写崩了。我会在bt之后再frame 1、frame 2各看一遍把关键参数的值记下来细心的开发者很快就能发现端倪。还有一个高频问题段错误发生在库函数里比如memcpy。单独看这一帧没什么线索真正的Bug往往在调用方——传了非法指针、长度不对、目标缓冲区太小。所以遇到libc库函数崩溃先别纠结库内部直接往上翻一到两帧看调用参数。定位后如果要看崩溃附近的汇编和寄存器用(gdb) x/10i $pc-16 # 反汇编崩溃点附近指令 (gdb) info registers # 查看寄存器值 (gdb) x/gx $rsp # 看栈上数据对于段错误$pc指向的指令往往能直接说明问题如果是访问某个非法地址指令里能看出来如果是call到非法地址说明函数指针坏了。这套组合在无符号环境下尤其重要。4.3 优化编译下的崩溃怎么查工作上的崩溃绝大多数发生在release环境也就是-O2编译。这种core用GDB打开后bt经常有告警Backtrace stopped: previous frame inner to this frame而且变量大量显示optimized out。这不是GDB坏了是编译器把代码重新编排了源码映射关系变得不连续。这种情况我的建议是尽量用与线上同版本的源代码和构建配置重新编一份带-g的二进制但别用-O2 -g覆盖线上单独编一份分析用。虽然性能差异不影响崩溃分析符号信息是准的。优先相信汇编。bt显示的函数名即使乱汇编栈上的返回地址是真实存在的。用x/a $rsp手工读栈也可以找回部分调用链。如果内存布局被优化破坏了但core里寄存器还在info registers加上反汇编配合存的源码仍然能拼出大致现场。说句实在话优化模式下有些变量就是拿不回来这一点GDB做得也确实不如一些商业调试器。但优化崩溃的核心诉求是知道崩在哪个函数、顺着调用链找到调用者这一点打开符号的优化版还是能做到的。真到了完全看不到栈的地步就要考虑在线上代码里加日志、或者在关键函数入口/出口埋点重新发布这属于另一个话题了。5. 进阶玩法TUI 界面、调试脚本与远程调试5.1 TUI 模式不用 IDE 也能看源码很多人不知道GDB自带了半图形化界面TUIText User Interface用法是在GDB里执行(gdb) layout src (gdb) layout asm (gdb) layout split也支持启动时直接gdb -tui ./my_program。TUI模式下窗口上半部分显示当前源码或汇编下半部分是命令交互区单步时上面的高亮行会跟着走体验比纯命令行好太多。常用快捷键Ctrl-x a退出/进入TUI。Ctrl-x 1单窗口布局。Ctrl-x 2双窗口布局源码汇编。Ctrl-l重绘屏幕窗口花屏时救命的。TUI偶尔会出现花屏或者输入错乱终端宽度不够也会导致排版崩坏。真遇到就按Ctrl-l重绘再不行就退出TUI回到纯命令行功能一点都不损失。5.2 GDB 脚本与自定义命令GDB支持启动时自动读取.gdbinit文件里面可以放常用配置。我个人的.gdbinit大概是这样的set pagination off set print pretty on set print array-indexes on set print elements 100 set print repeats 32 handle SIGPIPE nostop noprint逐个解释下set pagination off输出长列表时不翻页方便日志保存。刚学时翻页经常卡得不知所措。set print pretty结构体按字段格式化打印不然全挤在一行里根本看不清嵌套。set print elements限制打印字符串/数组长度防止超大数组把终端刷爆。set print repeats数组重复元素折叠显示。handle SIGPIPE nostop noprint忽略SIGPIPE信号程序写管道时很常见没人希望调试时总是中断在这里。.gdbinit还可以定义自定义命令相当于给GDB加宏。举个例子我想快速打印一个指针指向的字符串数组define ps if $argc 1 print *(char**)$arg010 else printf usage: ps ptr\n end end document ps Print next 10 string pointers from an array. end这里有个关键语法点$arg0代表第一个参数$argc是参数个数。定义好之后ps arr一下就能打印数组里的多个字符串指针比反复敲print arr[0]、print arr[1]高效得多。复杂的调试流程也可以直接写脚本文件在GDB里source debug.cmd加载执行。我把排查崩溃的整套命令就放到一个脚本里拿到core后一条source全跑完几句输出就能定位七八成的问题。5.3 附加运行中进程与远程调试附加运行中进程前面提到过这里补充一个实践场景程序假死或者死循环但没崩。先用gdb -p PID附加然后thread apply all bt看每个线程在哪。如果是死循环栈顶通常停在某几个函数里反复转如果是死锁会有多个线程同时卡在pthread_mutex_lock或者条件变量等待上。定位后detach退出程序继续跑线上影响很小。远程调试也是工作里经常用到的。目标机上跑gdbservergdbserver :1234 ./my_program开发机上用gdb ./my_program (gdb) target remote 目标机IP:1234这样就能像调试本机程序一样调试远端程序尤其适合嵌入式、容器里不方便交互的环境。有一点要留意gdbserver方式加载的是开发机上的本地符号所以本地的二进制和远端必须一致否则行号对不上。远程调试另一个常见场景是调试启动即崩溃的程序。目标机上直接gdbserver启动程序会在启动早期就停下来GDB连上后再continue可以观察到崩溃前所有状态这比改代码加日志快得多。6. 常见问题与排查技巧实录6.1 调试符号加载不上的几种原因调试中最常见的报错是No symbol table is loaded或者Breakpoint 1 failed。我总结下来就那么几个原因按概率排编译时没加-g或者加了之后被strip了。用file 二进制可以看出来是否带debug info。程序用了动态库GDB没找到库的符号文件。用set solib-search-path指定库路径或directory加源码路径。二进制和源码路径不一致。代码在别的机器/目录编译的GDB找不到源码文件这时用directory /path/to/src把源码路径指过去。判断依据很简单info sources会列出GDB已知的源文件啥也没有就是符号没加载。6.2 优化代码跳来跳去怎么破-O2下断点的最大痛点是你打在某一行的断点GDB会把它映射到最近的可断点指令上于是断点命中位置和源码行明显对不上。更烦的是有些行被完全消除了断点直接无效。给几个实用建议如果只是临时分析问题用-O0 -g编一份调试完再换回正常版本。同一份源码不可能同时在跑两个版本这是最省心的方案。想在生产版本里保留可调试性可以用-O1 -g折中。-O1的优化破坏性比-O2小很多变量还保留着。针对特定函数抑制优化把要调试的函数单独放到一个编译单元里用__attribute__((optimize(O0)))标记但这种方式在不同编译器上兼容性一般最好只在调试版本里临时用。真遇到优化到看不了变量就开汇编窗口用layout asm配合stepi走指令级再结合寄存器值判断逻辑。记住一个核心原则-O2调试时看到多少算多少不用强求每个变量都有值。关键是调用链和指令级别行为这两样在带-g的优化版本里依然可靠。6.3 死锁定位实例线程栈与信号最后用一个我实际排查过的典型场景带大家串一遍。现象程序跑着跑着完全卡死不崩溃、不退出top看CPU占用几乎为零。这种表现十有八九是死锁或者条件变量等待。操作流程(gdb) attach pid (gdb) thread apply all bt输出大概长这样Thread 3 (Thread 0x7f3a:1): #0 __lll_lock_wait () at .../lowlevellock.c #1 __pthread_mutex_lock (mutex0x7f3a...) #2 worker_thread (arg0x...) at worker.c:88 #3 start_thread () Thread 2 (Thread 0x7f3b:1): #0 __lll_lock_wait () #1 __pthread_mutex_lock (mutex0x7f3a...) #2 consumer_thread (arg0x...) at consumer.c:142 #3 start_thread ()两个线程都卡在__pthread_mutex_lock上再往下看锁地址。这里有个实用技巧mutex0x7f3a...这个地址同一个锁在多份输出里地址是一样的。我把两个线程对应的锁地址一对发现一致说明它们都在等同一把锁。再看谁持有这把锁需要一个没在等待的线程继续往下翻thread apply all bt的完整输出找找有没有线程正持有相关资源在跑别的操作。如果所有线程都在等锁而没有一个线程持有锁在推进典型死锁确认。确认之后按上面步骤回到代码看worker.c:88和consumer.c:142两处加锁的顺序是不是配对的。经典死锁往往是两个线程以相反顺序锁两把锁GDB的栈信息能直接提示哪里出了问题。附加在死锁现场还有个额外好处程序还活着数据都在内存里。你可以切到任意线程用frame、print看业务数据判断它们是卡在某批数据上还是各种状态异常。这一步往往能直接揭示死锁触发条件帮助复现。提示排查完死锁别忘了detach让程序退出别一直占着进程。有些公司还有专门的调试环境策略现场保留时间有限有机会就先把bt输出重定向到文件存下来(gdb) set logging file /tmp/deadlock_bt.txt (gdb) set logging enabled on (gdb) thread apply all bt (gdb) set logging enabled off留好现场后面慢慢分析。结尾用GDB这几年最大的体会是调试本身是有方法论的不是瞎试。拿到一个问题先判断是崩溃、卡死还是逻辑错误然后选择对应的调试路线——崩溃走core分析卡死走线程栈逻辑错误走断点加单步。把路线定清楚了大部分问题都能一步步缩小范围最终落到具体代码行。最后再分享一个小技巧GDB的命令支持Tab补全和缩写比如b就是breakc是continuen是nextp是printbt是backtrace。刚学时记全称没问题但用熟了之后全用缩写手速可以快不少。这对那些需要在现场快速操作的场景特别有用——很多时候早一分钟拿到现场就少复现一次Bug。

相关新闻

Codex 平替 Qoder 深度评测:迁移实操与避坑指南

Codex 平替 Qoder 深度评测:迁移实操与避坑指南

1. 从 Codex 的"断供焦虑"说起:为什么大家都在找平替最近几个月,AI 编程工具圈子里最常被问到的一句话就是:"Codex 还能用吗?"这个问题的背后,是大量开发者真实的焦虑——原本已经嵌进日常工作流的…

2026/10/17 6:21:45 阅读更多 →
再见PCDN,电脑必备的网络神器NetLimiter来了!

再见PCDN,电脑必备的网络神器NetLimiter来了!

看到这个话题300万浏览量的话题: 我相信很多用户和我一样,确实没想到「在线视频网站」也用了PCDN。 关于PCDN这门技术就不多做详细介绍了,大概的意思就是你在下载资源或观看视频的时候,你的资源也在上传。这样导致的结果就是网速变…

2026/10/17 6:20:45 阅读更多 →
Unity UGUI EventSystems事件分发与射线检测机制详解

Unity UGUI EventSystems事件分发与射线检测机制详解

1. 从一次点击穿透事故说起:为什么EventSystems值得单独拎出来讲做过Unity UGUI项目的人,大概率都遇到过这种场景:界面上弹出一个奖励面板,背景是半透明的遮罩,玩家点击遮罩外的区域时,底下的按钮居然被触发…

2026/10/17 6:20:45 阅读更多 →

最新新闻

Harbor私有镜像仓库部署与运维实践:从架构到避坑指南

Harbor私有镜像仓库部署与运维实践:从架构到避坑指南

一套业务系统跑了一两年,环境中几十上百个容器,镜像分散在各台机器甚至每个人电脑里,等到要统一发版、回滚版本的时候,才发现连一个准确的镜像清单都凑不出来。这种场景我想很多团队都经历过。所以当我的某位合作伙伴第一次提出“…

2026/10/17 6:54:01 阅读更多 →
Multi-Raft架构设计:从单Raft瓶颈到分布式分片扩展实践

Multi-Raft架构设计:从单Raft瓶颈到分布式分片扩展实践

1. 项目概述与核心目标如果你维护过一个采用 Raft 共识的分布式数据库,大概率会碰到这个场景:单组 Raft 的写吞吐量撑不住业务增长,CPU 和磁盘的扩展能力已经到顶,数据量稍微上来一些,日志复制的压力就像滚雪球一样越滚…

2026/10/17 6:54:01 阅读更多 →
AI大模型面试:RAG怎么处理PDF中的表格?AI不会管你的成本,不会管实现难度

AI大模型面试:RAG怎么处理PDF中的表格?AI不会管你的成本,不会管实现难度

文章目录 一、面试现场:一个问题暴露真实水平 二、表格为什么是RAG的"噩梦"? 2.1 切片即毁灭:表头和数据行被生生拆开 2.2 真实企业场景:表格远比你想象的复杂 2.3 网上那些"方案"为什么不切实际? 三、企业级三大解决方案(核心干货) 3.1 方案一:多…

2026/10/17 6:54:01 阅读更多 →
Linux-多文件工程

Linux-多文件工程

vsp 文件名 :分屏操作Ctrl ww :切换屏幕Ctrl w :平分大小wq:退出1. 其他 文件 .c只需包含自己的 .h 用 “ ” 包含2. 此时对应的 .h定义自己那一套 包别人 声明(结构体,函数)eg&#xff…

2026/10/17 6:54:01 阅读更多 →
西邮Linux兴趣小组2024纳新面试题

西邮Linux兴趣小组2024纳新面试题

西邮Linux兴趣小组2024纳新面试题 0.聪明的吗喽 猴子每走一米会消耗掉三根香蕉,分别是往前走一米会消耗一根,返回起点会消耗一根,再搬另外50根会再消耗一根,一共消耗三根,所以我们只需要找到一个中转站,使香…

2026/10/17 6:54:01 阅读更多 →
Linux本地NTP时间服务器搭建与高可用运维实践

Linux本地NTP时间服务器搭建与高可用运维实践

1. 项目概述:为什么你需要一个本地时间服务器,而不是直接靠公网NTP?“ntpd建立本地时间服务器供所有本地linux服务器使用”——这句话背后藏着一个被很多运维新人忽略的硬伤:时间不同步不是小问题,而是系统性风险的导火…

2026/10/17 6:53:01 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →