C 如何用zlib正确地打开和关闭已经打开的gzip文件?
我正在编写一个小型C库,它读取作为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(普通文件); 返回
文件*
传递的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警告,我