kernel cleanup
前言“goto error”模式因引入不易察觉的资源泄漏而臭名昭著。在已经存在多个展开条件的代码路径中添加新的资源获取约束既繁琐又容易出错。“cleanup”辅助函数可以帮助编译器减轻这种繁琐的工作并有助于维护后进先出LIFO的展开顺序从而避免意外的资源泄漏。前备知识1. 语句表达式在 C 语言中({ ... })并不是标准 C 语言的原生语法而是GNU C 编译器GCC提供的一种扩展语法通常被称为语句表达式Statement Expression。这种语法允许你将一系列语句如变量声明、控制流语句if-else,for,switch等包裹在括号中并将其作为一个整体表达式来使用。返回值该语法块中最后一条语句的结果即为整个({ ... })表达式的返回值。作为右值由于它支持返回值因此可以作为表达式的右值使用这在普通的do { ... } while(0)宏中是无法实现的。与do { ... } while(0)的对比在 C 语言宏封装中除了({ ... })更常见的是do { ... } while(0)。两者的主要区别在于do { ... } while(0)无法返回值不能作为表达式的右值但它是标准 C 语法跨平台兼容性极好。({ ... })支持返回值可以参与复杂的表达式计算但它是 GNU C 扩展在非 GCC 兼容的编译器如某些环境下的 MSVC中可能会报错与逗号表达式对比内部能承载的代码复杂度不同逗号表达式只能包含表达式Expressions。你不能在里面声明变量也不能写if-else、for等控制流语句。语句表达式可以包含任意 C 语句Statements。你可以在里面声明局部变量、写循环、条件判断甚至调用返回void的函数。作用域隔离能力不同逗号表达式没有自己的作用域。如果在里面使用了变量它直接操作的是外部的变量。语句表达式有独立的作用域。在({ ... })内部声明的变量出了这个括号就失效了不会污染外部命名空间。这对于编写安全的宏至关重要。标准支持度不同逗号表达式是ISO C 标准语法任何 C 语言编译器GCC, MSVC, Clang都完美支持。语句表达式是GNU C 扩展语法。如果代码要在不支持 GCC 扩展的编译器如 Windows 下的 MSVC上编译会直接报错。核心应用场景的差异逗号表达式主要用于for循环中同时更新多个变量或者在宏中执行简单的副作用操作如打印日志并返回一个计算值。语句表达式主要用于底层开发如 Linux 内核中的高级宏定义。当宏需要执行多步复杂操作、需要临时变量来避免参数多次求值的副作用且必须返回一个值时语句表达式是唯一的标准替代方案在没有它之前只能借助外部指针参数或复杂的嵌套宏来实现。你可以把逗号表达式理解为“一行代码能写完的简单流水线”而语句表达式则是“一个可以打包成单个零件的小型车间”。2. 标记连接运算符## 字符串化运算符#3. 可变参数宏声明语法类似于可变参数函数逗号后面三个句点...表示一个或多个参数。但常见编译器也允许传递0个参数。[2][3]宏扩展时使用特殊标识符__VA_ARGS__表示所传递的参数的替换。变量宏扩展是指与具有可变自变量数的宏相关的 C99 和标准 C 的两个扩展。 一个扩展是用于将变量参数标识从__VA_ARGS__重命名为用户定义的标识的机制。 当未指定变量自变量时另一个扩展提供了一种方法来除去变量宏中的悬空逗号。使用__VA_ARGS__宏表示可变参数...#define debug(...) printf(__VA_ARGS__)给可以参数取了一个名称argsGNU C扩展语法#define debug(format, args...) printf(format, args)如果可变参数被忽略或为空“##”操作将使预处理器(preprocessor)去除掉它前面的那个逗号#define debug(format, args...) printf(format, ##args)eg: debug(123) printf(123),而不是printf(123,)[这样会引起编译报错]第一部分 DEFINE_FREEDEFINE_FREE(...) - 定义free(或者说cleanup)函数1. _name 名称去标识2. _type: free的数据类型3. _free: 用户自定义的清理语句__free(...) - 使用free(或者说cleanup)函数1. _name: 上面定义提到的标识的名称#define DEFINE_FREE(_name, _type, _free) \ static __always_inline void __free_##_name(void *p) { _type _T *(_type *)p; _free; } #define __free(_name) __cleanup(__free_##_name)return_ptr(p) - 返回p的同时抑制_free()原理 通过一个临时变量保存p变量的指针然后把p设为NULL 返回临时变量保存的p变量的指针 p为NULL 就不会执行_free(). 一般地_free if(_T) kfree(_T);#define __get_and_null(p, nullvalue) \ ({ \ auto __ptr (p); \ auto __val *__ptr; \ *__ptr nullvalue; \ __val; \ }) static __always_inline __must_check const volatile void * __must_check_fn(const volatile void *val) { return val; } #define no_free_ptr(p) \ ((typeof(p)) __must_check_fn((__force const volatile void *)__get_and_null(p, NULL))) #define return_ptr(p) return no_free_ptr(p)第二部分 DEFINE_CLASSDEFINE_CLASS(name, type, exit, init, init_args...): 用于定义 type 析构函数destructor和构造函数constructor的辅助函数helper。 exit 是一个使用 _T 的表达式 -- 类似于上面的 FREE。 init 是 init_args 中的一个表达式其结果为 type EXTEND_CLASS(name, ext, init, init_args...): 将类 name 拓展为 nameext并使用新的构造函数new constructor CLASS(name, var)(args...): 将变量 var 声明为命名类name的实例 CLASS_INIT(name, var, init_expr): 将变量 var 声明为命名类name的实例并使用自定义初始化表达式init_expr。代码 DEFINE_CLASS#define DEFINE_CLASS(_name, _type, _exit, _init, _init_args...) \ typedef _type class_##_name##_t; \ typedef _type lock_##_name##_t; \ static __always_inline void class_##_name##_destructor(_type *p) \ __no_context_analysis \ { _type _T *p; _exit; } \ static __always_inline _type class_##_name##_constructor(_init_args) \ __no_context_analysis \ { _type t _init; return t; } #define CLASS(_name, var) \ class_##_name##_t var __cleanup(class_##_name##_destructor) \ class_##_name##_constructor #define CLASS_INIT(_name, _var, _init_expr) \ class_##_name##_t _var __cleanup(class_##_name##_destructor) (_init_expr)扩展定义类 - EXTEND_CLASS#define EXTEND_CLASS_COND(_name, ext, _cond, _init, _init_args...) \ typedef lock_##_name##_t lock_##_name##ext##_t; \ typedef class_##_name##_t class_##_name##ext##_t; \ static __always_inline void class_##_name##ext##_destructor(class_##_name##_t *_T) \ { if (_cond) return; class_##_name##_destructor(_T); } \ static __always_inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \ __no_context_analysis \ { class_##_name##_t t _init; return t; } #define EXTEND_CLASS(_name, ext, _init, _init_args...) \ EXTEND_CLASS_COND(_name, ext, 0, _init, _init_args)include/linux/compiler.h /* Format: __UNIQUE_ID_name___COUNTER__ */ //__COUNTER__是一个从0开始的计数器每次使用这个宏时它的值会自动加1 #define __UNIQUE_ID(name) \ __PASTE(__UNIQUE_ID_, \ __PASTE(name, \ __PASTE(_, __COUNTER__))) include/linux/compiler_types.h #define ___PASTE(a, b) a##b #define __PASTE(a, b) ___PASTE(a, b) include/linux/compiler_attributes.h #define __always_inline inline __attribute__((__always_inline__)) #define __cleanup(func) __attribute__((__cleanup__(func))) ​

相关新闻

local.ai桌面应用使用详解:Tauri框架打造的跨平台体验

local.ai桌面应用使用详解:Tauri框架打造的跨平台体验

local.ai桌面应用使用详解:Tauri框架打造的跨平台体验 【免费下载链接】local.ai 🎒 local.ai - Run AI locally on your PC! 项目地址: https://gitcode.com/gh_mirrors/lo/local.ai local.ai是一款基于Tauri框架开发的跨平台桌面应用&#xff0…

2026/7/22 23:36:25阅读更多 →
slm战斗思考帧同步

slm战斗思考帧同步

1.逻辑与渲染分离服务器全力跑,在while循环中,哪一帧播放了什么写到队列中。2.客户端则帧率30ms一帧,进行处理。他们调用共同的内核 TheMartix

2026/7/22 23:36:25阅读更多 →
键盘与手柄无缝切换:RetroAssembly空间导航功能详解

键盘与手柄无缝切换:RetroAssembly空间导航功能详解

键盘与手柄无缝切换:RetroAssembly空间导航功能详解 【免费下载链接】retro-assembly The personal retro game collection cabinet in your browser. Join us on Discord https://discord.gg/gwaKRAYG6t 项目地址: https://gitcode.com/gh_mirrors/re/retro-asse…

2026/7/22 23:36:25阅读更多 →
200行代码硬核读取ext4磁盘文件

200行代码硬核读取ext4磁盘文件

我们可能听说过很多文件系统,比如 FAT32、NTFS、EXT4,在linux 下 EXT4 是一个使用比较广泛的文件系统,前面的小节我们简单介绍了 EXT4 文件系统的内部结构,这个小节我们用硬核方式读取 EXT4 文件系统下 /etc/hosts 文件&#xff0…

2026/7/23 0:20:34阅读更多 →
2026年最新英语写作批改平台挑选指南 附实用避坑技巧

2026年最新英语写作批改平台挑选指南 附实用避坑技巧

文章摘要:随着英语写作批改需求快速增长,市场上涌现了大量智能批改工具,但质量参差不齐,普通用户往往难以甄别。本文旨在帮助读者厘清核心评估维度,从技术能力、场景适配、合规安全等角度系统梳理挑选标准,…

2026/7/23 0:20:34阅读更多 →
2026 Cloudflare 5秒盾解决指南:无限验证码、403拦截与Bot检测优化方法

2026 Cloudflare 5秒盾解决指南:无限验证码、403拦截与Bot检测优化方法

在2026年的企业数字化运营中,公开数据采集、自动化测试、SEO监控已成为核心基础设施。然而,随着 Cloudflare 将其防护机制全面升级为以 Turnstile(无感验证) 和 AI 驱动的行为生物识别(Behavioral Biometrics&#xff…

2026/7/23 0:20:34阅读更多 →
损失函数与训练细节——这些坑我替你踩过了

损失函数与训练细节——这些坑我替你踩过了

先聊聊 Loss 函数。语义分割最基础的 Loss 是 Cross-Entropy(交叉熵),简单粗暴,逐像素计算分类损失。但你很快会发现一个问题——类别不平衡。Cityscapes 里“道路”和“建筑”占了画面大半江山,而“摩托车”、“自行车…

2026/7/23 0:18:34阅读更多 →
Java volatile 到底解决什么问题:可见性、禁止重排与双重检查锁单例

Java volatile 到底解决什么问题:可见性、禁止重排与双重检查锁单例

Java volatile 到底解决什么问题:可见性、禁止重排与双重检查锁单例 面试问 volatile,十有八九会答「保证可见性、不保证原子性」。这话没错,但真到写代码时就懵了:什么时候该加 volatile?为什么单例的双重检查锁一定要加它?加了 volatile 的 count 为什么还是会错?这篇把这…

2026/7/23 0:18:34阅读更多 →
Agent编排:别再纠结选LangChain还是LangGraph了

Agent编排:别再纠结选LangChain还是LangGraph了

内容速览章节核心内容一、编排到底是什么Workflow vs Agent、编排在架构中的位置二、七种编排模式Prompt Chaining / Routing / Parallelization / ReAct / Plan-and-Execute / Orchestrator-workers / Evaluator-Optimizer三、生产环境绕不开的问题会话管理、并发控制、错误分…

2026/7/23 0:18:34阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 0:53:59阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 0:53:59阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 0:53:59阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:00:28阅读更多 →
从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:28阅读更多 →
油泥处理设备哪里能买到

油泥处理设备哪里能买到

油泥处理设备哪里有?这是许多从事油田、炼化、清罐业务的从业者最关心的问题。根据河南三丰环保设备有限公司的行业经验,选购油泥处理设备的核心在于设备能否适配当地环保法规与原料特性,而非单纯看价格。该公司总经理王钦田先生指出&#xf…

2026/7/23 0:00:28阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/22 22:56:18阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/22 18:55:50阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/22 18:55:50阅读更多 →