进程退出时 C++ 析构到底会不会执行?——从 Chromium 架构看“故意泄漏”的工程哲学

进程退出时 C++ 析构函数执行之谜:从一次崩溃到 Chromium 的取舍 C++ 进程退出时,析构函数是否一定会执行,并不是一个简单的“是”或“否”的问题。不同退出路径如 main 正常 return、std::exit、_exit,以及异常展开、线程终止等场景,析构行为差异显著。局部对象依赖栈展开销毁,静态对象则通过 atexit 注册回调触发销毁,而 _exit 则跳过一切用户态清理,直接由操作系统回收全部资源。理解这些底层原理,对排查 Core Dump、规避退出阶段多线程竞态至关重要。而在高并发服务端与 Chromium 这类大型工程中,常以“确定性优先、内核代清理”的策 阅读详情

在日常 C++ 开发里,我们从小被教育:

RAII 是王道
new 一定要 delete
对象生命周期必须严谨管理

但当你进入 Chromium / 浏览器内核 / 大型常驻进程系统 的世界后,会发现一件非常“反常识”的事:

❗ 大量对象 new 了故意不 delete
❗ 单例用裸指针 + static
❗ 进程退出时 根本不走析构

很多工程师第一次看到类似代码时都会震惊:

ShortcutKey* ShortcutKey::GetInstance(Profile* profile) { static ShortcutKey* instance = nullptr; if (!instance) instance = new ShortcutKey(profile->GetOriginalProfile()); return instance; } 

这不是内存泄漏吗???

答案是:

在浏览器进程里,这是“设计”,不是 Bug。

今天我们就从操作系统层、C++ 运行时层、Chromium 架构层三层,把这件事讲透。


一、进程退出那一刻,操作系统到底干了什么?

先打破第一个误区:

❌ “程序退出时,系统会帮你调用析构函数”

错。操作系统根本不知道什么是 C++。

当浏览器进程结束时(无论是正常关闭还是被 kill),OS 做的事情非常“物理”:

操作说明
回收整块虚拟内存直接把进程地址空间抹掉
关闭内核对象文件句柄、socket、管道
停止线程调度所有线程终止

它不会做的事情:

不会发生原因
调用类析构函数OS 不认识 C++ 对象
调用 deleteOS 不知道堆分配
调用 vector / string 析构语言层行为
调用单例析构静态对象逻辑属于运行时

也就是说:

内存被回收 ≠ 对象被析构


二、什么时候析构才会被调用?

析构是否执行,取决于 进程是怎么退出的。

退出方式析构是否执行
return 0; from main✅ 会
exit()✅ 会执行 atexit + 静态析构
std::terminate()❌ 不保证
_exit()❌ 完全不执行
被 Task Manager 杀进程❌ 不执行
崩溃(Crash)❌ 不执行

而浏览器的现实是:

绝大部分异常退出路径都不会走析构链


三、那为什么还要 RAII?

这里是关键认知转折点:

RAII 是为了“运行时资源安全”,不是为了“进程结束清理”。

RAII 解决的是:

场景是否需要析构
函数退出释放锁必须
作用域结束释放文件必须
线程结束释放资源必须
进程结束没必要

因为:

进程结束 = 整个宇宙被抹掉


四、Chromium 为什么“故意不析构”?

这是浏览器架构最核心的稳定性策略之一。

退出阶段是全局最不稳定状态

进程退出时:

  • 线程在停止

  • IO 线程可能已经销毁

  • 日志系统可能已关闭

  • UI 线程正在 shutdown

  • 单例析构顺序不可控

如果这时还让对象析构,会发生什么?

情况后果
A 析构里访问 B 单例B 已析构 → 崩溃
析构里打日志日志系统已死
析构里发 IPCIPC 通道已关
析构里加锁锁已销毁

所以 Chromium 的原则是:

🔥 退出阶段禁止复杂逻辑


五、真正的风险不是“泄漏”,而是“析构”

这是很多人认知颠倒的地方。

在浏览器内核中:

行为危险程度
不 delete 内存❌ 几乎无害
析构里访问全局资源💀 极高风险
析构顺序不可控💀💀
退出阶段跑复杂逻辑💀💀💀

所以工程选择变成:

宁可泄漏,也不析构


六、为什么 OS 回收比析构安全?

因为 OS 的回收是:

✔ 原子级
✔ 无顺序依赖
✔ 无逻辑执行
✔ 不会崩溃

而析构是:

❌ 有顺序
❌ 有依赖
❌ 有逻辑
❌ 可能崩


七、Chromium 官方是怎么做的?

大量代码使用:

static base::NoDestructor<MyService> instance; 

它的本质是:

// 构造,但永不析构 

也有很多地方直接:

static Foo* g_foo = new Foo(); 

并明确标注:

// Intentionally leaked on shutdown. 

这是一种工程策略,不是疏忽。


八、什么时候必须析构?

只有一种情况:

对象管理的是“进程级别之外的资源”

比如:

资源是否必须主动释放
共享内存是
GPU context是
文件持久化缓冲是
数据库事务是

但 Chromium 也不会放在析构里,而是:

提供显式 Shutdown() 阶段


九、析构函数在浏览器中应该做什么?

正确答案:

几乎什么都不做

析构只应该处理:

  • 本对象的纯内存资源

  • 不依赖其他模块的内容


十、总结:浏览器世界的生命周期哲学

普通 C++浏览器内核
追求 0 leak追求 0 crash
析构是必须析构是风险
生命周期精细管理退出直接放弃
delete 是责任delete 是可选

一句话总结:

在浏览器进程里,“让 OS 收尸” 比 “优雅善终” 安全得多。


如果你现在在写浏览器、引擎、IDE、数据库、服务器这类常驻大进程系统,这套思维转变是必经之路。

Linux下C++程序强制终止与Chromium的故意泄漏设计 在Linux系统中,进程终止涉及复杂的内存管理与资源回收机制。当使用kill -9强制终止进程时,操作系统会直接回收所有资源而不执行析构函数,这是由SIGKILL信号的不可捕获特性决定的。现代C++开发中,RAII(资源获取即初始化)是管理资源生命周期的核心范式,但某些特殊场景下,如Chromium这样的复杂系统,开发者会刻意设计资源泄漏模式以提高稳定性。通过base::NoDestructor等模板,可以安全地绕过析构过程,这种工程实践在全局缓存、单例对象等场景中尤为常见。理解这种设计需要从操作系统原理、 阅读详情

相关推荐

Windows下构建C++编译沙箱:为AI Agent与异构系统提供标准化执行环境

在软件开发和系统集成领域,环境一致性与系统隔离是保障应用稳定运行的核心挑战。通过容器化技术(如Docker)与轻量级虚拟化(如WSL2)的结合,可以构建出标准化的编译与运行时环境,其原理是利用命名空间和控制组实现进程与资源的隔离。这一技术方案的价值在于,它能够为微服务架构和持续集成流水线提供可复现、可扩展的基础设施,尤其适用于需要集成高性能原生代码模块的场景。具体到工程实践,通过封装特定版本的GCC工具链和系统依赖库,可以打造一个专用于C++程序编译的轻量级沙箱。该沙箱能够被外部系统(如AI Agent调度

weixin_33806300的博客 412

C++进程退出时资源清理的工程实践与Chromium设计哲学

在C++程序设计中,资源管理是核心课题之一,RAII(资源获取即初始化)机制通过构造函数和析构函数自动管理资源生命周期。然而在进程退出场景下,传统资源清理方式可能引发性能损耗和稳定性风险。现代操作系统会在进程终止时自动回收内存和系统资源,这使得某些场景下跳过析构函数成为优化选择。Chromium浏览器作为大型C++工程代表,其多进程架构下的'故意泄漏'设计体现了工程实践的权衡艺术,特别适用于短期存活的子进程管理。该方案通过牺牲理论上的完美清理,换取了实际的性能提升和系统稳定性,这种思想对插件系统、微服务等场

weixin_30219613的博客 136

C++进阶核心:从内存管理到并发编程的工程实践指南

在计算机编程领域,内存管理和并发编程是构建高性能系统的两大基石。内存管理涉及程序如何高效、安全地分配和释放内存资源,其核心原理包括资源获取即初始化(RAII)和对象生命周期控制,这直接关系到程序的稳定性和性能。并发编程则解决多任务环境下资源共享与同步的问题,通过锁、原子操作等机制确保数据一致性。这些技术的价值在于能够显著提升软件执行效率,降低资源消耗,广泛应用于游戏服务器、高频交易系统等对性能敏感的领域。本文聚焦于C++语言中的具体实现,深入探讨RAII机制、智能指针、内存对齐优化以及多线程同步原语等关键主

409

C++进程退出时析构不一定执行:从标准库到Chromium的故意泄漏哲学

在C++工程实践中,资源管理与生命周期控制是开发者绕不开的核心议题,而进程退出时的对象析构行为更是隐藏着诸多陷阱。很多开发者默认局部对象和全局对象都会在退出时自动析构,但实际上,从main正常返回、调用exit、quick_exit、abort或被信号杀死,不同退出路径对析构的执行截然不同。理解这些差异,需要深入CRT启动代码、atexit注册机制以及操作系统的内存回收原理。大型项目如Chromium,则基于进程模型和退出期崩溃风险,大量采用“故意泄漏”模式,用base::NoDestructor等工具规避

weixin_28323057的博客 240

C++进阶:从语法到系统构建,掌握现代编程核心

C++作为一门强大的系统级编程语言,其核心价值在于高效、安全地构建复杂软件系统。理解其内存模型、并发机制和抽象设计是进阶的关键。从基础语法到高级特性,C++进阶的本质是从“语言使用者”向“系统构建者”的思维转变。这要求开发者深入掌握面向对象与泛型编程的精髓,熟练运用现代C++范式如智能指针、移动语义和Lambda表达式,以应对实际工程中的资源管理、性能优化和并发挑战。通过设计模式与工程实践的结合,开发者能够构建出高效、可维护的系统,例如实现一个线程安全的日志库,这自然涉及RAII、模板和并发编程等核心概念。

weixin_30889885的博客 384

DeepSeek Harness保姆级教程:Node.js+pnpm+Electron本地AI模型运行时详解

DeepSeek Harness是一种面向中小团队的本地化AI模型运行时环境,本质是轻量级AI模型操作系统,聚焦单机场景下的可控交付与工程化落地。其核心原理依托Node.js实现模型生命周期调度与文件系统监听,借助pnpm硬链接机制解决依赖冲突与CI/CD效率瓶颈,并通过Electron构建安全沙箱容器,实现模型能力向终端用户的可靠封装。该技术栈显著提升本地大模型在工业质检、医疗辅助、教育管理等边缘场景的部署确定性与运维可维护性,特别适用于需打包为.exe/.dmg交付、支持热更新及硬件外设(如串口)集成的

weixin_34111790的博客 368

进程退出时C++析构函数跑不跑?从RAII到Chromium故意泄漏哲学

RAII是C++资源管理的基石,但你是否想过,当进程真正退出时,析构函数是否一定会执行?从main函数正常返回到调用exit、quick_exit、abort或被信号杀死,不同退出路径下全局对象的析构行为千差万别。即便析构被触发,跨编译单元的析构顺序失控、多线程下的数据竞争、动态库的清理时机,都可能让退出阶段成为崩溃重灾区。大型多进程项目如Chromium,提出了反向的工程实践——故意不析构,将资源交还给操作系统内核统一回收。通过NoDestructor模式,把这一决策显式化,既避免退出阶段的脆弱性,也能绕

weixin_42520374的博客 176

指纹浏览器容器化之路:Docker 化运行无头指纹浏览器的裁剪与优化

本文揭示了在云原生环境下运行指纹浏览器矩阵的核心挑战与解决方案。通过分析原生Docker化Chromium的三大致命痛点(内存黑洞、CPU争抢、环境泄漏),提出从GN编译参数深度裁剪到Docker镜像分层构建的全链路优化策略。文章详细拆解了如何通过编译级剔除非核心功能、静态链接依赖库、使用轻量基础镜像等技术手段,将Chromium从200MB+瘦身至80MB,并解决容器化环境下的资源隔离与特征伪装问题。最终构建出高并发、低资源消耗且具备强隐匿性的云原生指纹浏览器引擎,为自动化矩阵运营提供工业级解决方案。

数据知道的博客 794

Chromium 源码剖析:base::NoDestructor——更安全的静态单例解决方案

Chromium源码中广泛使用base::NoDestructor类来实现单例模式,它通过不调用析构函数的方式解决传统静态局部变量在程序退出时的析构顺序问题。文章分析了传统单例实现可能导致"静态析构顺序崩溃"的隐患,详细介绍了NoDestructor的设计原理:使用placement new构造对象但不调用析构函数,依赖操作系统回收内存。该方案适用于进程级单例、全局配置等场景,但不适合需要显式释放资源的对象。相比旧版LazyInstance,NoDestructor具有更简洁、内存开销更

John_ToStr的博客 477

【LCMM实战指南】从增长混合模型到潜在类别轨迹分析的纵向数据建模

本文深入解析了LCMM(潜在类别混合模型)在纵向数据建模中的应用,对比了LCGA与GMM的核心差异与选择策略。通过R语言lcmm包的实战演练,详细展示了从数据模拟、模型拟合、类别数选择到结果解读的全流程,为识别数据中不同的发展轨迹亚型提供了系统指南。

weixin_29070861的博客 379

Android手机本地语音转文字实战:用FunASR+ONNX Runtime打造离线ASR应用(附模型下载)

本文详细介绍了如何在Android应用中集成FunASR和ONNX Runtime,构建高性能的离线语音识别系统。通过模型选择、工程化集成和性能调优等实战技巧,开发者可以实现本地语音转文字功能,有效保护用户隐私并提升响应速度。

weixin_29046611的博客 266

Chromium RESULT_CODE_HUNG 根因诊断与 WinDbg 实战定位

RESULT_CODE_HUNG 是 Chromium 渲染进程响应停滞的底层信号,本质是主进程对渲染进程‘心跳探测’超时(200ms)触发的主动隔离机制,区别于 OOM 等资源耗尽类错误。其原理源于多进程架构下的 IPC 健康检查,反映的是线程调度失灵而非 JavaScript 执行异常。技术价值在于精准识别进程级卡死——如 GPU 驱动死锁、V8 垃圾回收阻塞、第三方 DLL 注入挂起或 Mojo IPC 内核缺陷。典型应用场景包括 WebAssembly 密集型应用、Canvas/3D 地图、Elec

weixin_34185512的博客 461

android技术--------如何解决弹出键盘只影响当前fragment输入的窗口

题目比较长,也可能有很多人不明所以这东西有啥可写的,简单来说就是实现近似于Android Pad 上QQHD聊天的界面效果,搞了很长的事件,今天终于搞定。 android3.0新加了组件Fragment称之为碎片,对这个一无所知的请自觉补习。今天的阐述将基于此组件。 fragment可以放入activity中,并随activity的生命周期变化而变化,但当相应键盘事件的时候,就比较让人挠头了,

3505

C++异常与Rust Result:错误处理机制的设计哲学与性能权衡

错误处理是编程语言设计的核心问题,涉及程序健壮性与开发效率的平衡。从原理上看,错误处理机制可分为基于控制流跳转的异常模型和基于类型系统的值模型。C++异常采用栈展开和异常表机制实现非本地控制流转移,虽能分离关注点但带来运行时开销和二进制体积增大;Rust的Result类型将错误编码为普通值,通过编译期检查强制处理所有错误路径,实现零成本抽象。在技术价值层面,C++异常提供了灵活的抽象能力但牺牲了确定性性能,而Rust的错误值模型确保了内存安全和执行路径可预测性。应用场景上,高性能计算和嵌入式系统常禁用异常以

weixin_30263277的博客 410

2.数字芯片时序正确的前提—Max-transition

芯片物理设计中最基本的Max-transition检查

weixin_43868998的博客 5418

告别Qweb!用ReportBro在Odoo 13-19版本中5步搞定动态报表

本文介绍了如何在Odoo 13-19版本中使用ReportBro替代Qweb快速实现动态报表设计。通过5步集成指南,包括环境准备、前端集成、后端服务搭建等,展示了ReportBro在可视化设计、即时预览和多格式输出(PDF/XLSX)方面的优势,显著提升开发效率和报表灵活性。

mac99的博客 799

树莓派5真·生产力桌面:Wayland+Docker+Chromium深度调优

树莓派作为广为人知的ARM开发板,其桌面体验长期受限于X11架构、容器兼容性差与浏览器渲染低效等基础瓶颈。随着树莓派5搭载VideoCore VII GPU与cgroup v2内核,现代Linux桌面技术栈(Wayland窗口系统、systemd-user服务管理、Ozone-Chromium原生后端)开始真正释放硬件潜力。本文聚焦‘Chromium输入法失效’‘Docker安装失败’等高频搜索痛点,从GPU内存带宽分配、cgroup v2沙盒隔离、Wayland输入法协议桥接到Hyprland动态工作区调

weixin_34296641的博客 368

LLCC68芯片系统架构与LoRa驱动开发核心解析

LoRa射频收发器是低功耗广域物联网(LPWAN)的关键组件,其本质是集成了调制解调器、协议引擎、数据缓冲区与电源管理的专用SoC。理解其工作模式状态机(Sleep/Standby/TX/RX)与SPI主机接口时序规范,是实现稳定通信的基础。LLCC68通过寄存器映射与命令集双接口抽象硬件控制,支持LoRa扩频调制与FSK兼容模式,具备高链路预算(157 dB)和DC-DC/LDO动态电源切换能力。典型应用场景包括远距离传感器节点、智能表计与工业无线监测系统。本文深入剖析LLCC68的信号链路径、中断机制与

weixin_29859471的博客 281

深入解析Chromium ChannelProxy:跨线程IPC的线程安全代理

多进程架构下的进程间通信(IPC)是浏览器等复杂系统的核心基础设施,而线程安全设计则是其中的关键挑战。传统做法常依赖加锁保护共享资源,但锁粒度难以控制且易引发时序问题。Chromium给出的答案是用任务调度替代锁:通过TaskRunner将消息投递到专属IO线程,从根上消除数据竞争。ChannelProxy作为IPC::Channel的线程安全外壳,封装了消息发送、接收回调、过滤器链及生命周期管理,让调用方无需关心底层传输细节。其设计价值体现在任意线程安全发送消息、监听回调与IO线程分离、避免悬垂引用等方面

weixin_34122810的博客 325

Python 爬虫实战:爬取哔哩哔哩知识区,抓取高赞课程信息

哔哩哔哩(Bilibili)是一个广受欢迎的综合性视频社区,其中的知识区汇聚了大量优质的教育、科普、技术等课程内容。本文将指导读者如何使用 Python 爬虫技术从哔哩哔哩知识区抓取高赞课程信息,并进行数据分析。本文深入探究了利用 Python 爬虫技术从哔哩哔哩知识区抓取高赞课程信息的全流程。从前期的环境搭建、模拟登录,到核心的课程数据抓取、存储,再到后续的数据分析与可视化,都详细展开讲解并提供代码支持。通过此方法所获取的数据,能够助力创作者优化内容、用户发现优质课程、平台洞察用户需求。

u014481728的博客 1133

YOLO26涨点改进 | 全网独家首发 主干改进篇 | TGRS 2025 | RepViT-TD,告别庞大骨干!YOLO26 + RepViT-TD轻量又强大,实现更快更准的小目标检测!

本文提出将RepViT-TD轻量级主干网络应用于YOLO26目标检测框架,以提升小目标检测性能。RepViT-TD通过优化计算资源分配,强化前两层高分辨率特征提取能力,在保持轻量化的同时(仅4.85M参数)显著提升微小目标的检测精度(AI-TODv2数据集AP50达54.6%)。文章详细介绍了三种主干改进方案(RepVit_ldy1/2/3)的代码实现,并提供了完整的YAML配置文件修改指南,使模型能高效部署于边缘设备。实验表明,该方法在计算复杂度(38.19G FLOPs)和检测精度间取得了良好平衡。

Ai缝合怪、助力小伙伴高效发论文 326

BrowserSkill:基于Chromium DevTools Protocol的命令行浏览器调度器

浏览器自动化工具正从模拟用户操作转向深度调度计算资源。BrowserSkill作为一类新型CLI工具,摒弃WebDriver协议,直接对接Chromium DevTools Protocol(DTP),实现原子级页面控制、低延迟JS执行与进程级资源编排。其技术价值在于将浏览器解耦为可编程服务节点,支持无头渲染、结构化数据提取、内存快照分析及信创环境适配,广泛应用于价格监控、PDF自动生成、低代码集成与AI工作流预处理等工程场景。核心热词‘bsk’与‘DevTools Protocol’贯穿全链路设计,体现命

weixin_31842715的博客 292

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

BrowserSkill解析:Chromium底层能力直连与CDP协议实战

BrowserSkill并非独立工具,而是对Chromium原生命令行启动能力与DevTools Protocol(CDP)接口的工程化抽象。其核心原理在于绕过Playwright、Puppeteer等封装层,通过--remote-debugging-port、/json端点及Runtime.evaluate等CDP原生命令,实现进程级复用与毫秒级响应。这种‘零中间层’直连模式显著提升性能稳定性,适用于金融风控检测、信创环境合规自动化、LLM浏览器沙箱等强时效性与高可控性场景,是Web自动化技术栈中不可或缺

weixin_28832121的博客 305

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

AIO Sandbox:单进程多界面开发沙箱架构解析

现代开发者面临的核心挑战并非环境隔离,而是跨工具链的认知负荷——浏览器、终端、编辑器、文件系统与协议解析器之间频繁切换导致上下文断裂。AIO Sandbox 通过 Rust 运行时+CEF+WebAssembly 的深度集成,构建单进程地址空间内的多子系统协同架构,实现微秒级通信、原子化状态同步与统一权限模型。其本质是将传统松耦合工具链重构为有机工作流,尤其适用于全栈工程师、SRE 及技术负责人在 YOLOv10 配置验证、MCP 模块开发、蓝湖协同等高频场景中提升端到端调试效率。

weixin_31083901的博客 251

BrowserSkill:Chromium CDP 的轻量级 CLI 封装

Chromium DevTools Protocol(CDP)是浏览器自动化与调试的核心底层协议,其原理是通过 WebSocket 暴露渲染引擎的原生控制能力,实现 DOM 操作、脚本执行、网络拦截等原子级操作。该协议的技术价值在于绕过高阶抽象层,提供确定性、低开销、跨环境兼容的浏览器控制方式,广泛应用于 CI/CD 环境检测、信创系统适配(如麒麟OS、统信UOS)、老旧服务器(CentOS 7)的无GUI自动化场景。BrowserSkill 正是这一协议的极简命令行封装,不依赖 Node.js 或 Pyt

weixin_42635064的博客 186

easy-vibe 跨平台开发全景解析:从技术流派、适用边界到架构选型决策

跨平台开发(Cross-Platform Development)以"一次编写、处处运行"为目标,通过高度抽象的中间层(JavaScript / TypeScript / Dart)让单一代码仓库同时产出适配 iOS、Android、Windows、macOS 等不同操作系统的客户端程序。本篇技术指南以 Datawhale easy-vibe 课程体系中关于跨平台解决方案的完整章节为骨架,系统梳理

gitblog_00070的博客 422
上一篇: Chromium WeakPtr 深度解析:从生命周期管理到线程安全的全面指南
下一篇: 极致冷静的狂徒:攀岩家与投资家背后的同一套心智系统
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ปรัชญา แค้วคำมูล

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值