c - 如何使用 zlib 正确打开和关闭已打开的 gzip 文件?
问题描述
我正在编写一个小型 C 库,它读取作为FILE *
. 我正在使用 zlibgzdopen()
打开文件文件描述符:
int zOpenCloseTest(FILE *const plainFile) {
gzFile file = gzdopen(fileno(plainFile), "rb");
if(file == NULL) {
goto error;
}
if(gzclose_r(file) != Z_OK) {
goto error;
}
return 0;
error:
// gzdopen does not close fd if it fails
fclose(plainFile);
return -1;
}
int main() {
FILE *const file = fopen("test.xp", "rb");
if(file == NULL) {
return -1;
}
if(zOpenCloseTest(file) < 0) {
return -2;
}
return 0;
}
zlib 手册指出:
文件描述符是从调用获得的,如
open
,dup
,creat
,pipe
或fileno
(在文件之前已经用fopen
)打开过。[...]gzclose
返回的下一次调用gzFile
也将关闭文件描述符 fd,就像fclose(fdopen(fd), mode)
关闭文件描述符一样fd
。如果您想保持fd
打开状态,请使用fd = dup(fd_keep); gz = gzdopen(fd, mode);
. [...]如果您使用fileno()
从 a 获取文件描述符FILE *
,那么您将不得不使用dup()
避免close()
将文件描述符加倍。两者gzclose()
和fclose()
都会关闭关联的文件描述符,因此它们需要有不同的文件描述符。
我不想让文件保持打开状态,所以我不创建重复项。
Leak_StillReachable
使用 Valgrind memcheck ( ) 检查时,上述代码会在第 21 行 (fopen) 上产生错误--leak-check=full --show-leak-kinds=all --track-origins=yes --vgdb=no --track-fds=yes
。
在 Windows 上,它会因“调试断言失败!”而崩溃。(_osfile(fh) & FOPEN) close.cpp line 49
错误框。
两者都内置在“调试模式”中。
该库是更大的 CMake 项目的一部分,用户可以选择将其构建为静态库还是共享库。无论哪种情况,我都希望 zlib 静态链接到库。我最初认为崩溃是由于库和 zlib 之间的运行时库链接模式不匹配,但最小的示例表明情况并非如此?如果您检查 CMake 输出,您可以看到 zlib 是用/MDd
标志构建的,应该是这样。(现代)CMake 通常默认为 "MultiThreaded$<$CONFIG:Debug:Debug>DLL" for CMAKE_MSVC_RUNTIME_LIBRARY
.
我相信我忘记了关于文件描述符<->流关系如何工作的重要内容。代码可在 GitHub 上找到。该项目使用 Hunter 以 CMake 友好的方式自动设置 zlib。来源是跨平台的,mre 提供了安静 msvc 警告的定义。
解决方案
您没有按照 zlib 文档所说的去做,您自己在问题中强调了这一点。使用dup()
.
推荐阅读
- scala - Sbt 没有从当前目录加载项目
- qt-quick - 自动串行连接
- ios - iOS 14 小部件深度链接到 React-Native 应用程序失败
- database - NullPointerException 与 Hibernate criteriaQuery 间歇性发生
- mysql - SQL查询根据月度数据计算季度数据
- wordpress - 如何将“优惠结束”文本更改为西班牙语?
- python - 当字节来自 Python 中的 input() 时如何从字节创建 UUID
- spring - Spring:省略 GET 表单的 CSRF 令牌?
- javascript - Javascript 按钮启用或禁用
- c - 管道到 hexdump 时,用汇编编写的程序没有输出