1

我的问题是我的程序挂起使用 zlib 的deflate()功能。

我首先初始化 my 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 流:

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

然后我zOutStreamdeflateEnd().

kTrue最后一个压缩步骤的值将Z_FINISH标志发送到deflate(),而不是Z_NO_FLUSH

它挂在以下行:

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

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

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

如果我输入nextgdb那么这行代码被处理并且整个过程挂起,我在这行代码之前和之后使用日志语句来验证。“之前”日志语句显示,但“之后”语句不显示。

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

4

1 回答 1

5

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

例如:

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

... etc.

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

zStream.avail_in = strlen(myData);

可能想成为:

zStream.avail_in = strlen(myData) + 1;
于 2012-12-14T13:44:08.047 回答