zlib inflate возвращает ошибку буфера

Я пытаюсь распаковать zip-файл с помощью zlib (без использования каких-либо расширений или сторонних разработчиков). Изначально src_len — 48756255, а dest_len — 49209890. Первый проход в цикле while проходит нормально: err равен Z_OK, и начинается второй проход. На втором проходе, независимо от того, что я делаю, я получаю Z_BUF_ERROR от надувания. stream.total_out на данный момент равен 49034460, так что осталось немного, но stream.avail_in на втором проходе равен 0. В любом случае, я ожидаю, что inflate даст мне Z_STREAM_END. Я действительно не знаю, что происходит, может кто-нибудь помочь?

void compression::uncompress2(char* dest, unsigned dest_len, char* src, unsigned src_len) {
    TempAllocator ta;

    z_stream_s stream = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    stream.next_in = (Bytef*)src;
    stream.avail_in = (uInt)src_len;
    stream.next_out = (Bytef*)dest;
    stream.avail_out = (uInt)dest_len;
    stream.zalloc = zalloc;
    stream.zfree = zfree;
    stream.opaque = &ta;

    // no header
    int err = inflateInit2(&stream, -MAX_WBITS);
    XENSURE(err == Z_OK);

    bool done = false;
    while (!done) {    
        stream.next_out = (Bytef*)(dest + stream.total_out);
        stream.avail_out = dest_len - stream.total_out;

        err = inflate(&stream, Z_SYNC_FLUSH);
        if (err == Z_STREAM_END)
            done = true;
        else if (err != Z_OK) {
            break;
        }
    }

    err = inflateEnd(&stream);
    XENSURE(err == Z_OK);
}

person David Menard    schedule 02.02.2015    source источник
comment
Что такое TempAllocator. Это работает? Я делаю это следующим образом: pastebin.com/PdGWX4cc я использую inflate вместо inflate2, но вы можете изменить его и он все еще работает нормально.   -  person Brandon    schedule 02.02.2015
comment
Я попробовал код, который вы разместили, и я все еще получаю ошибку буфера в конце вместо stream_end   -  person David Menard    schedule 02.02.2015


Ответы (1)


inflate() будет обрабатывать как можно больше входных данных, используя доступные выходные данные. Как только он не сможет ни обработать ввод, ни произвести вывод, он вернет Z_BUF_ERROR.

В этом случае все входные данные обрабатываются, и остается свободное место для выходных данных, но конец потока не обнаруживается. Вы не получаете Z_STREAM_END, потому что по какой-то причине вы не предоставляете полный поток дефляции.

Вот некоторые другие комментарии к вашему коду. Ваш цикл ничего не делает, и установка next_out и avail_out в цикле ничего не делает. Вы не предоставляете ни нового ввода, ни нового выходного пространства в своем цикле, поэтому нет смысла иметь цикл. Единственная цель наличия цикла вокруг inflate() состоит в том, чтобы предоставить больше входных данных, предоставить больше выходного пространства или и то, и другое. Кроме того, когда inflate() возвращается, next_out и avail_out обновляются до следующего доступного места в выходном буфере и объема доступного места. Ваши операторы, которые устанавливают next_out и avail_out в цикле, устанавливают для них значения, которые у них уже есть.

В коде с правильными циклами вокруг inflate() Z_BUF_ERROR не является проблемой, и обработка может продолжаться. Однако, если вы ожидаете другого результата при следующем вызове inflate(), необходимо предоставить больше входных и/или выходных данных.

Нет необходимости инициализировать stream структурой из нулей. Последующие задания - это все, что вам нужно.

person Mark Adler    schedule 02.02.2015