如何使用 zlib 正确打开和关闭已经打开的 gzip 文件?
How to properly open and close an already fopened gzip file with zlib?
我正在编写一个小型 C 库,用于读取作为 FILE *
传递的 gzip 文件。我正在使用 zlib 的 gzdopen()
打开文件文件描述符:
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 manual 状态:
File descriptors are obtained from calls like open
, dup
, creat
, pipe
or fileno
(in the file has been previously opened with fopen
). [...] The next call of gzclose
on the returned gzFile
will also close the file descriptor fd, just like fclose(fdopen(fd), mode)
closes the file descriptor fd
. If you want to keep fd
open, use fd = dup(fd_keep); gz = gzdopen(fd, mode);
. [...] If you are using fileno()
to get the file descriptor from a FILE *
, then you will have to use dup()
to avoid double-close()
ing the file descriptor. Both gzclose()
and fclose()
will close the associated file descriptor, so they need to have different file descriptors.
我不想让文件保持打开状态,所以我不创建重复文件。
当使用 Valgrind memcheck (--leak-check=full --show-leak-kinds=all --track-origins=yes --vgdb=no --track-fds=yes
) 检查时,上述代码在第 21 行 (fopen) 上产生 Leak_StillReachable
错误。
在 windows,它崩溃并显示“调试断言失败!” (_osfile(fh) & FOPEN) close.cpp line 49
错误框。
两者都是在“调试模式”下构建的。
该库是一个更大的 CMake 项目的一部分,用户可以选择将其构建为静态库还是共享库。无论哪种情况,我都希望将 zlib 静态 linked 到库中。
我最初认为崩溃是由于库和 zlib 之间的 运行-time 库 link 模式不匹配造成的,但最小的例子表明情况并非如此?
如果您检查 CMake 输出,您可以看到 zlib 正在使用 /MDd
标志构建,这是应该的。
(现代)CMake 通常默认为 CMAKE_MSVC_RUNTIME_LIBRARY
.
的“MultiThreaded$<$CONFIG:Debug:Debug>DLL”
我想我忘记了一些关于文件描述符<->流关系如何工作的重要信息。
code is available on GitHub。该项目使用 Hunter 以 CMake 友好的方式自动设置 zlib。
来源是跨平台的,mre 提供定义来消除 msvc 警告。
您没有按照 zlib 文档所说的去做,您自己在问题中强调了这一点。使用 dup()
.
我正在编写一个小型 C 库,用于读取作为 FILE *
传递的 gzip 文件。我正在使用 zlib 的 gzdopen()
打开文件文件描述符:
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 manual 状态:
File descriptors are obtained from calls like
open
,dup
,creat
,pipe
orfileno
(in the file has been previously opened withfopen
). [...] The next call ofgzclose
on the returnedgzFile
will also close the file descriptor fd, just likefclose(fdopen(fd), mode)
closes the file descriptorfd
. If you want to keepfd
open, usefd = dup(fd_keep); gz = gzdopen(fd, mode);
. [...] If you are usingfileno()
to get the file descriptor from aFILE *
, then you will have to usedup()
to avoid double-close()
ing the file descriptor. Bothgzclose()
andfclose()
will close the associated file descriptor, so they need to have different file descriptors.
我不想让文件保持打开状态,所以我不创建重复文件。
当使用 Valgrind memcheck (--leak-check=full --show-leak-kinds=all --track-origins=yes --vgdb=no --track-fds=yes
) 检查时,上述代码在第 21 行 (fopen) 上产生 Leak_StillReachable
错误。
在 windows,它崩溃并显示“调试断言失败!” (_osfile(fh) & FOPEN) close.cpp line 49
错误框。
两者都是在“调试模式”下构建的。
该库是一个更大的 CMake 项目的一部分,用户可以选择将其构建为静态库还是共享库。无论哪种情况,我都希望将 zlib 静态 linked 到库中。
我最初认为崩溃是由于库和 zlib 之间的 运行-time 库 link 模式不匹配造成的,但最小的例子表明情况并非如此?
如果您检查 CMake 输出,您可以看到 zlib 正在使用 /MDd
标志构建,这是应该的。
(现代)CMake 通常默认为 CMAKE_MSVC_RUNTIME_LIBRARY
.
我想我忘记了一些关于文件描述符<->流关系如何工作的重要信息。 code is available on GitHub。该项目使用 Hunter 以 CMake 友好的方式自动设置 zlib。 来源是跨平台的,mre 提供定义来消除 msvc 警告。
您没有按照 zlib 文档所说的去做,您自己在问题中强调了这一点。使用 dup()
.