如何检查FILE*文件指针是否合法可用?_Placeholder含义是什么
FILE指针合法性校验方法
- 基础空指针校验:调用文件操作接口前先判断
if (uFile == nullptr),先排除空指针异常 - 系统层句柄校验:Windows平台可调用
_fileno(uFile)获取C运行时文件描述符,再调用_get_osfhandle(fd)判断返回值,如果等于INVALID_HANDLE_VALUE说明文件句柄已失效;Linux平台可调用fcntl(fileno(uFile), F_GETFL),返回-1则说明句柄无效 - 流状态校验:调用
ferror(uFile),返回非0值说明文件流已出现IO错误;调用feof(uFile)判断是否已经读到文件末尾,排除读取偏移超过文件实际大小的情况 - 接口返回值校验:你当前的代码未判断
fseek和fread的返回值,fseek执行成功返回0,失败返回非0;fread返回实际读到的元素个数,若返回值远小于传入的m_lLenEncodedBytes,说明要么流已失效,要么读取范围超出文件实际大小 - 多线程安全排查:如果多个线程同时操作同一个FILE*指针,其他线程提前调用了
fclose也会导致当前线程的指针失效,建议加互斥锁保护整个文件操作流程
_Placeholder字段含义
你观察到的_Placeholder是微软MSVC标准库中FILE结构体的内部保留字段,不同状态下取值逻辑如下:
- 文件流正常打开时,
_Placeholder指向内部关联的文件句柄、IO缓冲区相关的有效内存地址 - 当文件已经被
fclose关闭、或者对应的FILE结构体内存被释放时,_Placeholder会被置为无效标记值。你失效场景下的取值属于Windows调试堆的典型释放标记0xfeeefeee,直接说明当前用到的FILE结构体已经被释放,这就是你读取内容全为0的根本原因
代码改进示例
void CAudioDataItem::finalizeItem_ReadEncodedBytesWithoutDecoding(FILE* uFile, CLog* uLog, double& uTimeReadEncodedBytes) { // 空指针校验 if (!uFile) { if (uLog) uLog->WriteLine("文件指针为空"); return; } // 句柄有效性校验(Windows平台实现) int fd = _fileno(uFile); if (_get_osfhandle(fd) == INVALID_HANDLE_VALUE) { if (uLog) uLog->WriteLine("文件句柄已失效"); return; } // 偏移操作校验 int seekRet = fseek(uFile, iFirstByteToRead, SEEK_SET); if (seekRet != 0) { if (uLog) uLog->WriteLine("fseek执行失败,错误码:%d", ferror(uFile)); return; } // 读取操作校验 size_t actualRead = fread(&m_EncodedBytes[0], sizeof(unsigned char), m_lLenEncodedBytes, uFile); if (actualRead != m_lLenEncodedBytes) { if (uLog) uLog->WriteLine("读取字节数不足,预期:%lld,实际:%lld", m_lLenEncodedBytes, actualRead); return; } }
内容的提问来源于stack exchange,提问作者tmighty
相关产品推荐
相关产品推荐

