为什么zlib deflate()挂?

时间:2012-12-14 12:41:49

标签: c stream gdb zlib deflate

我的问题是我的程序依赖于使用zlib的deflate()函数。

我首先初始化我的z_stream,如下所示:

int setupGzipOutputStream(z_stream zStream) {
    int zError;
    zStream.zalloc = Z_NULL;
    zStream.zfree = Z_NULL;
    zStream.opaque = Z_NULL;

    zError = deflateInit(&zStream, Z_COMPRESSION_LEVEL);

    /* error handling code to test if zError != Z_OK... */
    return EXIT_SUCCESS;
}

我尝试使用以下函数将数据写入我的z-stream:

int compressDataToGzipOutputStream(unsigned char *myData, z_stream zStream, Boolean flushZStreamFlag) {
    int zError;
    int zOutHave;
    FILE *outFp = stdout;
    unsigned char zBuffer[Z_BUFFER_MAX_LENGTH] = {0};

    zStream.next_in = myData;
    zStream.avail_in = strlen(myData); /* myData is a null-terminated string */
    do {
        zStream.avail_out = Z_BUFFER_MAX_LENGTH;
        zStream.next_out = zBuffer;

        zError = deflate(&zStream, (flushZStreamFlag == kFalse) ? Z_NO_FLUSH : Z_FINISH);

        /* error handling code to test if zError != Z_OK... */
        zOutHave = Z_BUFFER_MAX_LENGTH - zStream.avail_out;
        fwrite(zBuffer, sizeof(unsigned char), zOutHave, outFp);
        fflush(outFp);
    } while (zStream.avail_out == 0);

    return EXIT_SUCCESS;
}

我将这两个函数(简化为了提出这个问题的目的)称为如下:

z_stream zOutStream;

setupGzipOutputStream(zOutStream);

compressDataToGzipOutputStream(data, zOutStream, kFalse); 
compressDataToGzipOutputStream(data, zOutStream, kFalse);
...
compressDataToGzipOutputStream(data, zOutStream, kTrue);

然后我用zOutStream分解deflateEnd()结构。

上一个压缩步骤的kTrue值会将Z_FINISH标记发送到deflate(),而不是Z_NO_FLUSH

它挂在以下一行:

zError = deflate(&zStream, (flushZStreamFlag == kFalse) ? Z_NO_FLUSH : Z_FINISH);

然后我尝试使用gdb。我在这一行设置break,这是程序挂起的行。

在此断点处,我可以看到变量zStreamflushZStreamFlag和其他变量的值。 zStream变量不是NULL,我可以使用print zStreamprint zStream.next_in等验证这些变量,这些变量填充了我感兴趣的数据。

如果我在next中键入gdb,则会处理此行代码,并且整个过程会挂起,我会在此代码行之前和之后使用日志语句进行验证。显示“之前”日志语句,但“之后”语句不显示。

我的问题是:为什么deflate()悬在这里?我没有正确初始化输出流吗?没有正确使用deflate()?我一直在试图解决这个问题,但是没有运气。感谢您提出的任何建议。

1 个答案:

答案 0 :(得分:5)

你的函数应该使用指向z_stream的指针,而不是传入结构。你的init函数初始化什么是有效的本地副本,它将被丢弃。然后你的压缩函数会传递一个垃圾z_stream。

e.g:

int setupGzipOutputStream(z_stream *zStream) {
    int zError;
    zStream->zalloc = Z_NULL;
    ...
}

... etc.

看起来您的压缩函数没有考虑字符串末尾的null,因此当您尝试重新膨胀数据时可能会导致问题。

zStream.avail_in = strlen(myData);

可能希望成为:

zStream.avail_in = strlen(myData) + 1;