zlib compress()返回Z_BUF_错误,尽管为compressBound的结果分配了缓冲区(文件太大?)
使用zlib时,尽管我认为缓冲区分配是正确的,但当我试图压缩13G的文件时,调用zlib compress()返回Z_BUF_错误,尽管为compressBound的结果分配了缓冲区(文件太大?),c,compression,zlib,C,Compression,Zlib,使用zlib时,尽管我认为缓冲区分配是正确的,但当我试图压缩13G的文件时,调用compress()会产生Z_BUF_错误。这段代码适用于较小的文件 struct stat infile_stat; FILE *fp = NULL; if ((fp = fopen(md_of_name, "r")) == NULL) { fprintf(stderr, "Error: Unable to open file %s.\n", md_of_name);
compress()
会产生Z_BUF_错误。这段代码适用于较小的文件
struct stat infile_stat;
FILE *fp = NULL;
if ((fp = fopen(md_of_name, "r")) == NULL) {
fprintf(stderr,
"Error: Unable to open file %s.\n",
md_of_name);
exit(1);
}
stat(md_of_name, &infile_stat);
size_t u_len = infile_stat.st_size;
char *u_buf = (char *)malloc(u_len);
if (u_buf == NULL) {
fprintf(stderr, "Error: Unable to malloc enough memory for the "
"uncompressed buffer\n");
exit(1);
}
if (fread(u_buf, 1, u_len, fp) < u_len) { // d
fprintf(stderr,
"Error: Unable to read in all of file %s. Exiting.\n ",
md_of_name);
exit(1);
}
fclose(fp);
size_t c_len = compressBound(u_len);
Bytef *c_buf = (Bytef *)malloc(c_len);
if (c_buf == NULL) {
fprintf(stderr, "Error: Unable to malloc enough memory for the "
"compressed BIM buffer\n");
exit(1);
}
fprintf(stderr, "u_len:%lu\tc_len:%lu\tc_buf:%p\n", u_len, c_len, c_buf);
int r = compress(c_buf, &c_len, (Bytef *)u_buf, u_len);
if (r == Z_MEM_ERROR)
fprintf(stderr, "Not enough memory\n");
else if (r == Z_BUF_ERROR)
fprintf(stderr, "Not enough room in the output buffer.\n");
assert(r == Z_OK);
然后是断言失败
更新
我相信这个错误是由于zlib中compress()
函数内部的强制转换问题造成的。如果我是正确的,则在zlib 1.2.8的compress.c
的第40行返回错误,这是
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
stream.avail\u out
变量在上面几行设置为:
stream.avail_in = (uInt)sourceLen;
我认为演员阵容才是问题所在sourceLen
是一个无符号长字符,当它被转换为uInt时,位被丢弃。在我的例子中,sourceLen
是13922075353,destLen
是13926324460(fromcompressBound()
),但由于cast流的缘故。avail\u out
是1041422572。因此出现了错误
如果这是正确的,那么缓冲区的大小有一个隐式的界限。我现在不明白的是为什么缓冲区大小是无符号长的。它们需要是无符号整数。现在我知道要查找什么了,我在中看到了这个问题的地址,其中指出compress()
和uncompress()
可能限制为4GB,因为它们在单个调用中运行。”
我仍然认为压缩和解压缩不应将大小作为无符号长。对于如此大的大小,需要使用deflateInit()
,deflate()
,和deflateEnd()
通过将类型从无符号长更改为显式,在compress()参数中显式显示大小是否有用(这意味着一个非常大的最大值)转换为unsigned int?特别是因为这些long会立即转换为int?否。zlib的下一个版本不会转换为unsigned int。
stream.avail_in = (uInt)sourceLen;