尽管缓冲区分配给compressBound的结果(文件太大?),zlib compress()返回Z_BUF_ERROR

时间:2014-12-01 15:07:55

标签: c compression zlib

当使用zlib时,当我尝试压缩13G的文件时,我对compress()的调用给出Z_BUF_ERROR,尽管我认为这是正确的缓冲区分配。此代码适用于较小的文件。

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);

当我在13922075353字节的文件上运行它时,输出为:

u_len:13922075353   c_len:13926324460   c_buf:0x7f2b82436010
Not enough room in the output buffer.

其次是断言失败。

更新

我认为这个错误是zlib中compress()函数内部的转换问题的结果。如果我是正确的,则在zlib 1.2.8中的compress.c的第40行返回错误

if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;

stream.avail_out变量设置在上面几行:

stream.avail_in = (uInt)sourceLen;

我相信演员是个问题。 sourceLen是无符号长整数,当它被转换为uInt位时被删除。在我的情况下,sourceLen是13922075353,destLen是13926324460(来自compressBound()),但由于演员stream.avail_out是1041422572.因此错误。

如果这是正确的,则缓冲区的大小存在隐式限制。我现在不明白的是为什么缓冲区大小是无符号长的。它们需要是无符号的整数。

2 个答案:

答案 0 :(得分:0)

现在,我知道要查找的内容,我发现此问题是zlib FAQ中的地址,其中指出compress()uncompress()可能限制为4GB,因为它们在一个电话。&#34;

我仍然认为压缩和解压缩不应该将大小视为无符号长。

答案 1 :(得分:0)

对于那些大的东西,您需要使用deflateInit()deflate()deflateEnd()