Почему зависает zlib deflate()?

Моя проблема в том, что моя программа зависает при использовании функции deflate() zlib.

Сначала я инициализирую свой 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);

Затем я разбиваю структуру zOutStream на deflateEnd().

Значение kTrue на последнем шаге сжатия отправляет флаг Z_FINISH в deflate() вместо Z_NO_FLUSH.

Он висит на следующей строке:

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

Затем я попытался использовать gdb. Я поставил break на этой строке, строке, где зависает программа.

В этой точке останова я вижу значения переменных zStream, flushZStreamFlag и других. Переменная zStream не является NULL, что я могу проверить с помощью print zStream, print zStream.next_in и т. д., которые заполнены интересующими меня данными.

Если я наберу next в gdb, то эта строка кода будет обработана, и весь процесс зависнет, что я проверяю с помощью операторов журнала до и после этой строки кода. Оператор журнала «до» отображается, а оператор «после» - нет.

У меня вопрос: почему здесь висит deflate()? Я неправильно инициализирую выходной поток? Не правильно используете deflate()? Я бился головой о стену, пытаясь решить эту проблему, но не повезло. Спасибо за любой совет, который у вас может быть.


person Alex Reynolds    schedule 14.12.2012    source источник


Ответы (1)


Ваши функции должны принимать указатель на z_stream, а не передавать структуру. Ваша функция инициализации инициализирует то, что фактически является локальной копией, которая будет отброшена. Тогда вашей функции сжатия будет передан мусор z_stream.

e.g:

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

... etc.

Также похоже, что ваша функция сжатия не принимает во внимание нуль в конце строки, поэтому это может вызвать проблемы при попытке повторного заполнения ваших данных.

zStream.avail_in = strlen(myData);

Может хотеть быть:

zStream.avail_in = strlen(myData) + 1;
person JasonD    schedule 14.12.2012