根本原因是Windows默认独占打开文件;fopen无法控制共享模式,CreateFile需设dwShareMode为FILE_SHARE_READ或FILE_SHARE_READ|FILE_SHARE_WRITE;_fsopen虽简化但不跨平台且需检查返回值。

为什么 fopen 或 CreateFile 报错“文件被占用”,而你确定没人在用?
根本原因不是文件真被锁死,而是 Windows 默认以独占方式打开文件——哪怕你只读,系统也默认拒绝其他进程同时打开。C++ 标准库的 fopen 完全不提供共享模式控制;Win32 的 CreateFile 才能真正指定 dwShareMode,比如 FILE_SHARE_READ。很多开发者卡在这儿,以为是权限或路径问题,其实只是没绕过 C 运行时的封装限制。
CreateFile 怎么设 SH_DENYNO 对应的共享标志?
SH_DENYNO 是旧 C 运行时(如 MSVCRT)里 _fsopen 用的宏,它对应 Win32 层的 FILE_SHARE_READ | FILE_SHARE_WRITE。直接调 CreateFile 时别搜这个宏名,它不参与底层 API 调用:
-
dwShareMode = 0→ 完全独占(等效于SH_DENYRW) -
dwShareMode = FILE_SHARE_READ→ 允许别人只读(最常用) -
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE→ 允许别人读+写(即SH_DENYNO语义) - 注意:即使设了共享,对方打开时仍需主动声明兼容模式,否则照样失败
用 _fsopen 替代 fopen 是否更简单?
可以,但得清楚它的行为边界和陷阱:
-
_fsopen("log.txt", "r", _SH_DENYNO)确实等效于FILE_SHARE_READ | FILE_SHARE_WRITE - 但它仍是 C 运行时封装,底层还是调
CreateFile,性能无差异 - 不跨平台:Linux/macOS 没这函数,移植时得条件编译或重写
- 容易漏掉错误检查:
_fsopen失败返回NULL,但很多人直接解引用,触发崩溃 - 示例安全写法:
FILE* fp = _fsopen("data.bin", "rb", _SH_DENYNO); if (!fp) { // 检查 GetLastError() 得到具体原因,比如 ERROR_SHARING_VIOLATION return; }
共享模式设对了还是打不开?检查这三处
常见盲区不在代码本身,而在协作逻辑和环境约束:
立即学习“C++免费学习笔记(深入)”;
- 目标文件是否被设为“只读”属性?Windows 下只读文件 +
FILE_SHARE_WRITE会静默失败 - 另一个进程是否以
CREATE_ALWAYS或TRUNCATE_EXISTING方式打开?这类标志隐含独占语义,你的共享设置无效 - 杀毒软件或备份工具正在扫描该文件——它们常以高权限+独占方式打开,且不释放句柄,此时连
Process Explorer都可能看不到持有者
真正难处理的是第三方软件强占场景,这时候靠改共享模式没用,得协调生命周期或换用命名管道、内存映射等替代方案。



















