2013-11-01 2 views
1

Я только что столкнулся с довольно странным поведением libz. Если я просто использую компресс функция все работает нормально, но если я попытаюсь, например. сохранить сжатые данные в файл, я получаю Z_BUF_ERROR. Что я делаю не так?libz compress сбой при сохранении данных

#include <iostream> 
#include <fstream> 

#include "zlib.h" 

typedef unsigned char byte_t; 

static int read_filesize(const char* filename) { 
    int size = -1; 
    std::ifstream file(filename); 
    if (!file.is_open()) return size; 

    file.seekg(0, std::ios::end); 
    size = (int) file.tellg(); 
    file.close(); 

    return size; 
} 

static bool read_binary_file(const char* filename, byte_t* dst, const unsigned length) { 
    std::ifstream file(filename, std::ios::binary); 
    if (!file.is_open()) return false; 

    file.read((char*) dst, length); 
    file.close(); 

    return true; 
} 

static bool save_binary_file(const char* filename, const byte_t* src, const unsigned length) { 
    std::ofstream file(filename, std::ios::binary); 
    if (!file.is_open()) return false; 

    file.write((const char*) src, length); 
    file.close(); 

    return true; 
} 

int main(int args, char **argv) { 
    int fileSize = read_filesize(argv[1]); 
    byte_t fileData[fileSize]; 
    bool result = read_binary_file(argv[1], fileData, fileSize); 

    unsigned compressedSize = compressBound(fileSize); 
    byte_t compressed[compressedSize]; 

    int compressionResult = compress(compressed, (unsigned long*) &compressedSize, fileData, fileSize); 

    switch (compressionResult) { 
    case Z_OK: 
     std::cout << "Compression succeeded!\n"; 
     break; 

    case Z_MEM_ERROR: 
     std::cout << "Error: Z_MEM_ERROR!\n"; 
     return 1; 

    case Z_BUF_ERROR: 
     std::cout << "Error: Z_BUF_ERROR!\n"; 
     return 1; 

    default: 
     std::cout << "Error: UNDEFINED!\n"; 
     return 1; 
    } 

    std::cout << "Size of '" << argv[1] << "': " << fileSize << "\n" 
      << "After: " << compressedSize << "\n"; 

    bool saveResult = save_binary_file("file.bin.z", compressed, compressedSize); // everything works if I remove this instruction 

    return 0; 
} 
+0

Какой ** C++ ** компилятор вы используете, что позволяет VLA? ('byte_t fileData [fileSize];') – WhozCraig

+0

@WhozCraig Я использую * g ++ 4.8.2 * – Robin92

+0

Не шутите? Я не знал. Спасибо за информацию. – WhozCraig

ответ

3

из комментариев выше, кажется, что вы используете 64-разрядную архитектуру где sizeof(unsigned long)==8, в то время как sizeof(unsigned)==4.

Таким образом, литой (unsigned long*)&compressedSize, где compressedSize имеет тип unsigned, производит Неопределенное поведение.

Простое изменение объявления compressedSize на тип unsigned long должно исправить эту проблему.

0

Переполнение стека? Я не знаю, как динамические массивы реализованы в g ++, но если они помещены в стек, могут возникнуть проблемы с большими файлами. Используйте std::vector или std::array.

+0

Что это касается моей проблемы? Я знаю о ограничениях стека, поэтому я тестирую этот код на его источнике (~ 1 кБ), и я уверяю вас, что это не проблема в моей системе. – Robin92

0
int fileSize = read_filesize(argv[1]); 
byte_t fileData[fileSize]; 

Это VLA (массив переменной длины). Они не должны использоваться. Вместо этого используйте std :: vector. То же самое относится и к compressed

Смежные вопросы