关键在于createfile的dwsharemode参数:不设file_share_delete才能防删,只读属性对deletefile无效,句柄关闭或进程退出即解锁,推荐用临时文件+原子替换更可靠。

用 CreateFile 设置文件共享模式才是关键
Windows 下“锁定文件”不是靠改属性,而是靠打开时拒绝其他进程的访问权限。很多人误以为设 FILE_ATTRIBUTE_READONLY 或用 SetFileAttributes 就能防删,其实只影响写入,对 DeleteFile 完全无效——只要权限够,只读文件照样秒删。
真正起作用的是 CreateFile 的 dwShareMode 参数。想让文件不被删除,必须确保没有其他进程以 FILE_SHARE_DELETE 打开它。你自己打开时,就别放行这个标志:
-
CreateFile(L"test.txt", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, ...)—— 允许别人读/写,但不允删除 - 如果传
FILE_SHARE_DELETE,等于主动给他人开了删除后门 - 句柄不关闭,锁就一直有效;进程退出或调用
CloseHandle后,锁自动释放
为什么 SetFileAttributes + 只读没用
设置 FILE_ATTRIBUTE_READONLY 仅影响打开方式:比如 CreateFile(..., GENERIC_WRITE, ...) 会失败,但 DeleteFile 不检查这个标志,只要用户有目录的写权限(WRITE_DAC / DELETE_CHILD),就能删。
常见误解场景:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 资源管理器里右键 → 属性 → 勾“只读” → 以为安全了 → 实际上命令行
del test.txt照常成功 - 用
SetFileAttributes(path, FILE_ATTRIBUTE_READONLY)后,再用记事本打开保存,系统会悄悄清除只读位再写入 - NTFS 权限比只读属性更底层,但配置复杂、易误配,且不解决“自己程序运行中被删”的问题
进程崩溃导致锁失效?得加异常保护
用 CreateFile 拿到句柄后,如果程序中途崩溃或未正常 CloseHandle,Windows 会自动回收句柄,锁立刻消失——这时候别人就能删了。
稳妥做法不是依赖“永不崩溃”,而是缩短暴露窗口:
- 只在真正需要保护的临界段才保持句柄打开(比如写配置前 → 打开带独占 delete 权限 → 写完 → 关闭)
- 避免全局长期持有一个
HANDLE,尤其跨线程或异步 IO 场景下容易泄漏 - 可配合
SetUnhandledExceptionFilter或结构化异常处理(SEH)做兜底关闭,但注意 C++ 异常和 SEH 不自动互通
替代方案:用临时重命名 + 原子替换更可靠
如果目标只是“防止写一半被删导致数据损坏”,比死守一个句柄更健壮的做法是避开直接操作目标文件:
- 写新内容到
config.tmp - 用
MoveFileEx(old, new, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)原子替换 - 这个 API 在 NTFS 上是原子的,且
MOVEFILE_WRITE_THROUGH能减少缓存导致的假成功 - 即使替换中途崩溃,原文件完好,tmp 文件可被清理,不会留脏数据
真正的难点从来不是“怎么锁”,而是“锁多久、谁来关、崩了怎么办”。句柄锁是瞬态防御,设计上得默认它随时会失效。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










