Linux下SIGFPE信号深度解析:从整数除零到信号处理实战
1. 从一个让无数开发者抓狂的报错说起APPLICATION TERMINATED WITH THE EXIT STRING: Floating point exception (signal 8)——这行字但凡在Linux环境下写过C/C、做过科学计算、跑过数值仿真或者维护过高性能服务的人大概率都在深夜的终端里见过它。第一次遇到的人往往会陷入一种迷惑我的代码里明明没有浮点运算为什么给我报浮点异常更诡异的是程序不是抛出一个可以捕获的异常而是直接整个进程被内核干掉了连堆栈信息都不给你留。这个报错的本质是操作系统向进程发送了SIGFPE信号编号8而进程没有注册对应的信号处理函数于是默认行为就是终止进程并可能生成core dump。注意SIGFPE这个名字有极强的误导性——它虽然叫“浮点异常”但实际上触发它的场景远不止浮点数运算错误。整数除零、整数溢出、模运算除零甚至某些架构下的非对齐内存访问都可能让内核给你递上这个信号。这篇文章面向的是所有在Linux/Unix环境下做系统编程、数值计算、嵌入式开发、高性能服务端开发的工程师也包括那些用Python、Java等语言但底层依赖了native库的开发者——因为这类问题经常从你意想不到的底层冒出来。我会从信号机制原理讲起拆解触发SIGFPE的各类真实场景给出可复现的代码示例、完整的排查工具链、gdb调试实录以及我在实际项目中踩过的坑和总结出的避坑清单。读完你不仅能定位这个报错还能建立起一套处理同类底层崩溃问题的通用方法论。2. 信号机制与SIGFPE的本质剖析2.1 信号8到底是什么内核与进程的通信语言在Linux的信号体系里每个信号都有一个编号和默认行为。SIGFPE的编号是8默认动作是Core——也就是终止进程并生成核心转储文件。这里有个关键点很多人忽略信号是内核发给进程的“通知”而不是进程自己产生的“异常”。当CPU执行一条除法指令发现除数为零时硬件会产生一个异常trap内核捕获这个硬件异常后将其转换为SIGFPE信号投递给当前进程。这个转换过程决定了几个重要特性。第一信号投递是异步的你无法用常规的try-catch去捕获它除非注册信号处理器。第二默认情况下进程直接死亡你看到的Floating point exception其实是shell比如bash在子进程被信号杀死后打印的提示信息格式就是APPLICATION TERMINATED WITH THE EXIT STRING: ...这类封装。第三是否生成core文件取决于系统的ulimit -c设置和/proc/sys/kernel/core_pattern配置。理解这一点非常关键你排查的不是一个“异常”而是一个“进程被信号杀死”的事件。排查思路因此完全不同——你需要的是找到哪条指令触发了硬件异常而不是找哪行代码抛了异常。2.2 为什么叫Floating point却和浮点关系不大历史上最早的Unix系统运行在PDP-11等机器上当时的硬件对浮点运算错误的处理就是通过这个信号。后来IEEE 754标准普及浮点除零默认产生Inf或NaN而不是陷阱但信号的名字被保留了下来。于是形成了今天这个尴尬局面真正因为浮点运算触发SIGFPE的情况反而很少除非显式启用了浮点陷阱绝大多数SIGFPE都是整数运算惹的祸。具体来说在x86-64架构上以下情况会触发SIGFPE整数除法idiv/div的除数为零整数除法结果溢出比如INT_MIN / -1因为结果INT_MAX1无法用有符号整数表示某些情况下INT_MIN % -1也会触发使用-ftrapv等编译选项时有符号整数溢出会触发在部分架构如某些ARM配置上非对齐访问也可能触发而浮点运算方面只有在显式启用浮点异常陷阱通过feenableexcept等后浮点除零、无效操作才会触发SIGFPE。默认情况下浮点除零是静默产生Inf的。注意很多人以为SIGFPE只和除法有关实际上取模运算%在底层也是除法指令除零同样触发。而且INT_MIN / -1这种溢出场景极其隐蔽因为除数不是零你根本想不到会崩。2.3 信号处理与默认行为的差异进程可以通过signal()或sigaction()注册SIGFPE的处理函数。注册之后进程不会立即死亡而是跳转到处理函数执行。但这带来一个陷阱SIGFPE是由硬件异常转换来的触发时CPU的指令指针RIP仍然指向那条出错的除法指令。如果你的处理函数返回而不是调用exit或longjmp进程会重新执行那条指令再次触发信号形成死循环。这就是为什么正确的SIGFPE处理函数通常要么记录信息后退出要么用siglongjmp跳转到一个安全的恢复点。我在一个数值计算项目里就遇到过这个问题同事注册了处理函数想“优雅降级”结果处理函数返回后进程疯狂刷屏最后被OOM killer干掉排查了半天才发现是信号处理函数返回导致的重复触发。3. 触发SIGFPE的典型场景全解析3.1 整数除零最常见也最容易定位整数除零是SIGFPE的头号来源。看下面这段代码#include stdio.h int main() { int a 10; int b 0; int c a / b; printf(%d\n, c); return 0; }编译运行后立刻得到Floating point exception (core dumped)。这类问题定位相对简单因为出错点就在除法那一行。但真实项目里除数往往来自用户输入、配置文件、网络数据或者上游计算结果你需要在除法前加防御性检查。我的经验是所有来自外部的数值在参与除法或取模前必须校验。不要相信“这个值不可能是零”这种假设。我见过一个服务因为配置文件里某个超时参数被误设为0导致计算速率时除零整个服务集群在滚动重启时全部崩溃。3.2 整数溢出INT_MIN除以-1的隐蔽陷阱这个场景比除零隐蔽得多#include stdio.h #include limits.h int main() { int a INT_MIN; int b -1; int c a / b; printf(%d\n, c); return 0; }除数不是零逻辑上看起来没问题但INT_MIN / -1的结果是2147483648超出了int的最大值2147483647硬件除法指令产生溢出异常内核投递SIGFPE。这个问题在x86上必现在ARM上行为可能不同有的返回INT_MIN。类似的还有INT_MIN % -1。这类问题的可怕之处在于它只在极端输入下触发测试时很难覆盖。防御方法是在做除法前判断if (b -1 a INT_MIN)或者干脆用更宽的类型如int64_t做运算再截断。3.3 浮点陷阱显式启用才会遇到的场景默认情况下浮点除零不触发SIGFPE但如果你调用了feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW)那么浮点除零、0.0/0.0、sqrt(-1)等操作就会触发信号。科学计算和金融计算领域有时会启用这些陷阱以便及早发现数值问题。#include stdio.h #include fenv.h #pragma STDC FENV_ACCESS ON int main() { feenableexcept(FE_DIVBYZERO); double a 1.0; double b 0.0; double c a / b; printf(%f\n, c); return 0; }这段代码在启用陷阱后会触发SIGFPE。排查这类问题时要检查代码里是否有feenableexcept调用以及是否链接了会修改浮点环境的第三方库。3.4 编译器优化与未定义行为的交互C/C标准里有符号整数溢出是未定义行为UB。编译器可以假设它不会发生从而做出各种优化。这意味着你的除零检查可能被优化掉int safe_div(int a, int b) { if (b 0) return 0; return a / b; }看起来没问题但如果编译器能证明b不为零比如通过前面的代码推断它可能把检查删掉。更危险的是某些优化会把a / b转换成乘法加移位这时除零的行为就完全不可预测了。我的建议是涉及除法的边界检查用volatile或者内存屏障阻止编译器过度优化或者用__builtin_trap()等显式手段。在关键路径上宁可牺牲一点性能也要保证行为确定。4. 完整排查流程与工具链实战4.1 第一步确认信号来源与core文件配置遇到报错后第一件事是确认是不是真的SIGFPE。用dmesg查看内核日志dmesg | tail -20你会看到类似traps: myapp[12345] trap divide error ip:4005a6 sp:7ffd... error:0的记录。trap divide error明确告诉你这是除法错误。接着检查core文件配置ulimit -c cat /proc/sys/kernel/core_pattern如果ulimit -c是0core文件不会生成你需要先ulimit -c unlimited再复现。core_pattern决定了core文件的命名和存放位置常见的有core、core.%p或者通过管道传给systemd-coredump。提示生产环境往往禁用了core dump。如果无法开启可以用catchsegv、gdb附加到进程或者用LD_PRELOAD注入信号处理器来捕获现场。4.2 第二步用gdb定位出错指令有了core文件用gdb加载gdb ./myapp core进入gdb后第一组命令bt info registers x/i $pcbt看调用栈info registers看寄存器值x/i $pc反汇编当前指令。如果是除法错误你会看到类似idiv %ecx的指令而%ecx的值是0。这时用frame N切换到上层栈帧用print查看变量值就能定位到具体的代码行。如果没有core文件可以用gdb --args ./myapp启动程序复现后gdb会自动停在信号处。或者用gdb -p PID附加到正在运行的进程然后continue等待信号。4.3 第三步用AddressSanitizer和UBSan提前拦截与其等崩溃了再排查不如在开发和测试阶段就用工具拦截。编译时加上gcc -fsanitizeundefined -fsanitizeaddress -g -O1 myapp.c -o myapp-fsanitizeundefinedUBSan会在运行时检测整数溢出、除零等未定义行为并打印详细的错误信息包括文件、行号和变量值。-fsanitizeaddressASan则检测内存错误。两者结合能在问题进入生产前就暴露出来。实测下来UBSan对INT_MIN / -1的检测非常准确会直接告诉你runtime error: division of -2147483648 by -1 cannot be represented in type int。这比事后用gdb分析core文件效率高得多。4.4 第四步静态分析与代码审查对于已经上线的代码可以用clang-tidy、cppcheck等静态分析工具扫描。它们能识别出潜在的除零风险、整数溢出等问题。配置示例clang-tidy myapp.c --checks-*,bugprone-*,cert-* --cert-int31-c等检查项专门针对整数溢出。虽然静态分析有误报但在关键模块上跑一遍往往能发现几个隐藏的定时炸弹。5. 常见问题速查与避坑经验5.1 问题速查表现象可能原因排查手段解决方案程序无征兆崩溃shell提示Floating point exception整数除零或溢出dmesg看trap类型gdb看core除法前校验除数用宽类型运算只在特定输入下崩溃INT_MIN/-1溢出UBSan编译复现特判边界值浮点运算后崩溃启用了浮点陷阱检查feenableexcept调用关闭陷阱或处理异常多线程程序偶发崩溃共享变量被改导致除零用TSan检测数据竞争加锁或原子操作优化等级改变后行为不同UB被编译器利用对比-O0和-O2行为消除UB用volatile5.2 避坑经验实录坑一信号处理函数返回导致死循环。前面提过SIGFPE处理函数返回会重新执行出错指令。我见过一个项目为了“记录日志后继续”在处理函数里只写了fprintf就返回结果进程陷入无限循环日志文件瞬间涨到几十GB把磁盘写满。正确做法是用siglongjmp跳转或者直接_exit。坑二以为浮点除零会崩溃。很多从其他语言转过来的开发者以为1.0/0.0会崩结果发现得到inf于是放松了警惕。但某天链接了一个启用了浮点陷阱的数学库同样的代码就崩了。所以不要依赖浮点除零的行为显式检查除数是否为零。坑三忽略编译器优化等级的影响。同一个除零bug在-O0下崩溃在-O2下可能因为UB被优化而“正常”运行掩盖了问题。上线后换个编译器版本又崩了。测试必须覆盖生产使用的优化等级。坑四core文件被systemd接管找不到。现代Linux发行版常用systemd-coredumpcore文件不在当前目录而是被压缩存到/var/lib/systemd/coredump/。用coredumpctl list和coredumpctl gdb来查看别傻傻地找core文件。坑五容器环境ulimit设置不生效。在Docker容器里ulimit -c unlimited可能被宿主机的配置覆盖。需要在docker run时加--ulimit core-1或者修改容器的/etc/security/limits.conf。这个坑我在K8s环境里踩过排查了半天才发现是容器运行时限制了core dump。5.3 防御性编程清单所有除法/取模运算前校验除数不为零对有符号整数除法特判INT_MIN / -1和INT_MIN % -1关键计算用int64_t或double等更宽类型减少溢出风险外部输入在参与运算前做范围校验开发和测试阶段开启UBSan和ASan信号处理函数中避免返回用longjmp或退出生产环境配置好core dump便于事后分析6. 从信号处理到系统化防御的进阶思路6.1 注册信号处理器获取现场信息虽然默认行为会生成core文件但在某些环境如容器、嵌入式设备里core dump不可用。这时可以注册SIGFPE处理器用backtrace()和backtrace_symbols()打印调用栈#define _GNU_SOURCE #include signal.h #include execinfo.h #include stdio.h #include stdlib.h #include unistd.h void sigfpe_handler(int sig, siginfo_t *info, void *ctx) { void *buffer[64]; int size backtrace(buffer, 64); fprintf(stderr, SIGFPE caught at address %p\n, info-si_addr); backtrace_symbols_fd(buffer, size, STDERR_FILENO); _exit(128 sig); } int main() { struct sigaction sa; sa.sa_sigaction sigfpe_handler; sa.sa_flags SA_SIGINFO; sigemptyset(sa.sa_mask); sigaction(SIGFPE, sa, NULL); // ... 业务代码 return 0; }注意info-si_addr在SIGFPE场景下通常是出错指令的地址结合backtrace能快速定位。但backtrace本身不是异步信号安全的在信号处理器里调用有风险生产环境慎用或者用-rdynamic编译并配合libunwind。6.2 用sigsetjmp实现可控恢复如果确实需要在除零后恢复执行比如数值计算中跳过无效点可以用sigsetjmp/siglongjmp#include setjmp.h #include signal.h static sigjmp_buf jmpbuf; void handler(int sig) { siglongjmp(jmpbuf, 1); } int safe_divide(int a, int b, int *result) { if (sigsetjmp(jmpbuf, 1) 0) { *result a / b; return 0; } else { return -1; // 除零恢复到这里 } }这种模式在解析器、计算器等场景有用但要注意siglongjmp之后信号掩码和浮点环境可能处于不确定状态需要手动恢复。而且它不能跨线程使用多线程环境下每个线程需要独立的jmp_buf。6.3 构建持续集成的崩溃检测流水线单靠人工排查效率太低。我的做法是在CI流水线里加入以下环节编译时开启-fsanitizeundefined,address跑单元测试用valgrind --toolmemcheck跑集成测试用afl-fuzz或libFuzzer对输入解析模块做模糊测试收集所有测试的core dump用脚本自动分析dmesg和coredumpctl这套组合拳下来SIGFPE这类问题基本在合并到主分支前就能被拦截。我在一个跨平台系统项目里推行这套流程后线上因信号崩溃的事故率下降了八成以上。6.4 跨语言场景的特殊处理如果你的项目是Python调用C扩展、Java通过JNI调用native库SIGFPE会直接杀死整个JVM或Python进程你连Python的异常栈都看不到。这时需要在native层注册信号处理器记录信息后调用abort()或_exit()用faulthandler模块Python或-XX:CreateCoredumpOnCrashJVM保留现场在JNI边界做好参数校验避免把非法值传入native层我处理过一个Python科学计算库的案例用户传入的数组里有个零值底层C代码做归一化时除零整个Python进程崩溃用户只看到Floating point exception完全不知道是哪个数组哪个元素的问题。后来在C层加了校验并抛出Python异常问题才变得可定位。7. 我个人在实际排查中的几点体会SIGFPE这类问题的排查最忌讳的就是“猜”。我见过太多人看到报错就去翻代码找除法结果找了半天发现是第三方库里的问题。正确的顺序永远是先用dmesg和gdb确认信号类型和出错地址再顺着调用栈往上找最后才看代码逻辑。另外不要在生产环境关闭core dump。虽然core文件占空间但它能在事故发生后给你最完整的现场。我的做法是配置core_pattern把core文件写到独立分区并设置定期清理。相比事故排查消耗的人力这点存储成本完全可以接受。最后分享一个实用技巧如果你怀疑是某个特定输入触发的可以用gdb的watch命令监控除数的内存地址一旦被改成零就断下来。命令是watch -l *(int*)0x地址配合条件断点能精准抓到“谁把除数改成了零”。这个技巧在排查多线程数据竞争导致的除零时特别管用。

相关新闻

船舶检测数据集实战:3000张YOLO格式样本与YOLOv8训练全解析

船舶检测数据集实战:3000张YOLO格式样本与YOLOv8训练全解析

做海事监测方向的项目,很多朋友问我的第一句话都是:有没有现成的船舶检测数据集?这个领域确实不像车辆检测那样有BDD100K、Cityscapes这种量级的公开资源,能找到一套能用、标注规范、场景覆盖还过得去的YOLO格式数据集&#xff0c…

2026/10/13 9:06:07 阅读更多 →
用WorkBuddy和MCP协议把量化回测压缩到一句话

用WorkBuddy和MCP协议把量化回测压缩到一句话

最近我把量化这条链路彻底换了个玩法:用 WorkBuddy 当 AI 操作台,把行情数据和回测引擎全部封装成 MCP 工具,之后你只需要用一句话说清楚“要哪只股票、什么周期、跑什么策略”,WorkBuddy 就会自己去拉数据、写策略、执行回测&…

2026/10/13 9:06:07 阅读更多 →
Elasticsearch 用户角色管理实战:从权限设计到避坑指南

Elasticsearch 用户角色管理实战:从权限设计到避坑指南

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

2026/10/13 9:05:05 阅读更多 →

最新新闻

WPF/WinForms上位机AI代码生成:把Codex auth.json改到TaoToken的串口通信实战

WPF/WinForms上位机AI代码生成:把Codex auth.json改到TaoToken的串口通信实战

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

2026/10/13 9:53:03 阅读更多 →
SGLang PD分离流程细节:Prefill与Decoding解耦的DP attention配置验证

SGLang PD分离流程细节:Prefill与Decoding解耦的DP attention配置验证

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

2026/10/13 9:53:03 阅读更多 →
Vision Transformer图像去雾:全局自注意力原理与PyTorch工程实践

Vision Transformer图像去雾:全局自注意力原理与PyTorch工程实践

简介:面向图像去雾与视觉Transformer研究者和开发者,提供基于Vision Transformer算法的完整Python实现,含源代码、预训练权重与详细使用说明。压缩包共340个文件,约156MB,其中204个Python脚本负责模型构建、训练参数配…

2026/10/13 9:53:03 阅读更多 →
线性代数本质是结构感知,不是矩阵计算

线性代数本质是结构感知,不是矩阵计算

1. 这门课不是“算矩阵”的,而是训练你识别结构的眼睛很多人第一次翻开《数学一线性代数》教材,看到行列式、矩阵乘法、特征值这些词,下意识就把它归类为“计算课”——仿佛只要多练几道题、背熟公式、把初等行变换步骤走对,就能拿…

2026/10/13 9:53:03 阅读更多 →
风筝检测数据集:VOC+YOLO双格式2260张单类别小目标基准

风筝检测数据集:VOC+YOLO双格式2260张单类别小目标基准

简介:本资源为面向计算机视觉初学者与目标检测实践者的风筝(kite)专用检测数据集,适用于YOLO系列、Faster R-CNN等主流目标检测模型的训练与验证。数据集提供Pascal VOC与YOLO双格式标注,共2260张高质量JPG图像&#x…

2026/10/13 9:53:03 阅读更多 →
Clearly快速上手:5分钟从安装到第一篇文档,掌握这款原生Markdown编辑器

Clearly快速上手:5分钟从安装到第一篇文档,掌握这款原生Markdown编辑器

【免费下载链接】clearly Markdown editor for Mac, iOS and iPadOS 项目地址: https://gitcode.com/gh_mirrors/cle/clearly 点击查看 免费下载 Clearly 是一款面向 Mac 和 iPhone 的原生 Markdown 编辑器:打开 .md 文件、带语法高亮地写作、一键切换实…

2026/10/13 9:52:03 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/12 21:05:09 阅读更多 →
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/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →