C 如何用zlib正确地打开和关闭已经打开的gzip文件?

C 如何用zlib正确地打开和关闭已经打开的gzip文件?,c,valgrind,zlib,c99,msvcrt,C,Valgrind,Zlib,C99,Msvcrt,我正在编写一个小型C库,它读取作为文件*传递的gzip文件。我正在使用zlib的gzdopen()打开文件描述符: int-zOpenCloseTest(文件*const-plainFile){ gzFile file=gzdopen(fileno(plainFile),“rb”); if(file==NULL){ 转到错误; } 如果(gzclose_r(文件)!=Z_OK){ 转到错误; } 返回0; 错误: //如果fd出现故障,gzdopen不会关闭fd fclose(普通文件); 返回

我正在编写一个小型C库,它读取作为
文件*
传递的gzip文件。我正在使用zlib的
gzdopen()
打开文件描述符:

int-zOpenCloseTest(文件*const-plainFile){
gzFile file=gzdopen(fileno(plainFile),“rb”);
if(file==NULL){
转到错误;
}
如果(gzclose_r(文件)!=Z_OK){
转到错误;
}
返回0;
错误:
//如果fd出现故障,gzdopen不会关闭fd
fclose(普通文件);
返回-1;
}
int main(){
FILE*const FILE=fopen(“test.xp”、“rb”);
if(file==NULL){
返回-1;
}
如果(测试(文件)<0){
返回-2;
}
返回0;
}
各国:

文件描述符是从调用中获取的,如
open
dup
create
pipe
fileno
(文件中以前使用
fopen
打开过)。[…]下次调用返回的
gzFile
上的
gzclose
也将关闭文件描述符fd,就像
fclose(fdopen(fd),mode)
关闭文件描述符
fd
一样。如果要保持
fd
打开,请使用
fd=dup(fd_keep);gz=gzdopen(fd,模式)。[…]如果使用
fileno()
文件*
获取文件描述符,则必须使用
dup()
以避免重复使用
close()
文件描述符。
同时使用
gzclose()
fclose()
将关闭关联的文件描述符,因此,它们需要有不同的文件描述符

我不想让文件保持打开状态,因此我不创建重复项

当使用Valgrind memcheck进行检查时,上述代码在第21行(fopen)上创建了一个
Leak\u StillReachable
错误(
--Leak check=full--show Leak kinds=all--track origins=yes--vgdb=no--track fds=yes
)。
在windows上,它会因“调试断言失败!”
(\u osfile(fh)&FOPEN)close.cpp第49行
错误框而崩溃

两者都是在“调试模式”下构建的

该库是更大的CMake项目的一部分,用户可以选择是将其构建为静态库还是共享库。无论哪种情况,我都希望zlib静态链接到库。 我最初认为崩溃是由于库和zlib之间的运行时库链接模式不匹配造成的,但最简单的示例表明情况并非如此? 如果您检查CMake输出,您可以看到zlib是用
/MDd
标志构建的,这是应该的。 (现代)对于
CMake\u MSVC\u RUNTIME\u库
,CMake通常默认为“多线程$DLL”

我想我忘记了一些关于文件描述符流关系如何工作的重要信息。 这个该项目使用Hunter以CMake友好的方式自动设置zlib。
源代码是跨平台的,mre提供了用于消除msvc警告的定义。

您没有按照zlib文档中的说明执行,您自己在问题中强调了这一点。使用
dup()

您没有按照zlib文档中的说明去做,您自己在问题中强调了这一点。使用
dup()。这类似于执行
close(fileno(fp))在stdio流上。您可能会执行以下操作:
fd=dup(fileno(plainFile))
fclose(普通文件)
file=gzdopen(fd)
if(gzclose\u r(file)!=Z\u OK){
close(fd);
返回-1;
}
。MS CRT可能希望您使用
\u dup
\u close
!问题是,zlib man明确声明“在返回的
gzFile
上调用
gzclose
也将关闭文件描述符
fd
,就像
fclose(fdopen(fd),mode)
fclose
接受一个
file*
并关闭整个文件,而不仅仅是描述符。我还强调了在
gzclose
之后建议不要呼叫
fclose
。关于mscrt警告,我将添加一条注释。谢谢!,你和马克·阿德勒让我意识到我真的需要修改我关于io的知识。在结束问题之前,我想问一下,为什么在
gzclose\r
的错误处理中放入
close(fd)
gzclose
失败时描述符能否保持打开状态?这将允许您在一个步骤中处理两个错误,因为如果
gzdopen
失败,则保证
gzclose
也会失败?看起来
gzclose
总是在文件描述符上调用
close
,除非它返回
Z_STREAM_ERROR
。如果返回值是
Z_ERRNO
,那么
close
返回了一个错误,我想根本的问题是
gzclose
关闭文件描述符,但对其上的stdio流一无所知。这类似于执行
close(fileno(fp))在stdio流上。您可能会执行以下操作:
fd=dup(fileno(plainFile))
fclose(普通文件)
file=gzdopen(fd)
if(gzclose\u r(file)!=Z\u OK){
close(fd);
返回-1;
}
。MS CRT可能希望您使用
\u dup
\u close
!问题是,zlib man明确声明“在返回的
gzFile
上调用
gzclose
也将关闭文件描述符
fd
,就像
fclose(fdopen(fd),mode)
fclose
接受一个
file*
并关闭整个文件,而不仅仅是描述符。我还强调了在
gzclose
之后建议不要呼叫
fclose
。正确的mscrt警告,我