简体   繁体   中英

C++ Program crashes when reading binary data from file of X length

I am trying to read binary data from a file, here is my file structure:

#define SIGNATURE_LENGTH 3
#define VERSION_LENGTH 2
#define DATACOUNT_LENGTH 4
#define COMPRESS_LENGTH 1
#define FORMAT_LENGTH 2
#define DATALENGTH_LENGTH 4

const unsigned char resSignature[SIGNATURE_LENGTH] = { 0x52, 0x45, 0x53 };
const unsigned char resVersion[VERSION_LENGTH] = { 0x01, 0x00 };

const unsigned char isCompressed[COMPRESS_LENGTH] = { 0x01 };
const unsigned char notCompressed[COMPRESS_LENGTH] = { 0x00 };

// Data Formats:
const unsigned char dataUnknown[FORMAT_LENGTH] = { 0x00, 0x00 };
const unsigned char dataXML[FORMAT_LENGTH] = { 0x01, 0x00 };


// Define header structure for resource file
struct ResHeader
{
    unsigned char signature[SIGNATURE_LENGTH];
    unsigned char version[VERSION_LENGTH];
};

// Define data structure for resource file
struct ResData
{
    unsigned char compressed[COMPRESS_LENGTH];
    unsigned char dataFormat[FORMAT_LENGTH];
    unsigned char dataLength[DATALENGTH_LENGTH];
    unsigned char *data;
};

And my class uses:

std::fstream File;

// Resource file makeup
ResHeader  header;
unsigned char dataCount[DATACOUNT_LENGTH];

// Vector to contain resource file data
std::vector<ResData> ResourceData;

The program crashes when I try to read from a file:

int ResourceFile::LoadFile()
{
    File.open("blah.dat", std::ios::in | std::ios::binary);

    // Read header
    File.read((char*) header.signature, SIGNATURE_LENGTH);
    File.read((char*) header.version, VERSION_LENGTH);
    if(!VerifyHeader())
    {
        File.close();
        return HEADER_INCORRECT;
    }
    File.read((char*) dataCount, DATACOUNT_LENGTH);
    long fileCount = unsignedCharArrayToLong(dataCount);
    for(long i = 0; i < fileCount; ++i)
    {
        ResData tmp;
        File.read((char*) tmp.compressed, COMPRESS_LENGTH);
        File.read((char*) tmp.dataFormat, FORMAT_LENGTH);
        File.read((char*) tmp.dataLength, DATALENGTH_LENGTH);
        File.read((char*) tmp.data, unsignedCharArrayToLong(tmp.dataLength));
        ResourceData.push_back(tmp);
    }
    File.close();
    return SUCCESS;
}

The program crashes on the line:

File.read((char*) tmp.data, unsignedCharArrayToLong(tmp.dataLength));

The length of the data in the file is 282, which is what is read into tmp.dataLength; so the number is accurate. The data is also compressed using easy zlib: http://www.firstobject.com/easy-zlib-c++-xml-compression.htm

Any suggestions/help as to what I am doing wrong or what I could be doing better would be appreciated. Thank you.

This local variable:

ResData tmp;

contains

unsigned char *data;

Given that none of the code actually assigns anything to data , it will be pointing at some "random" place in memory. Which means "undefined behaviour", and given the law of averages and your result, in this case "undefined behaviour" means your program crashes, which is probably better than the alternative, or you would have been scratching your head a lot more when it went wrong somewhere else.

You probably want something like this (after the read for dataLength ):

size_t len = unsignedCharArrayToLong(tmp.dataLength); 

tmp.data = new unsigned char[len];
File.read((char*) tmp.data, len);

Later on, don't forget to deallocate the data. Or better yet, use a std::vector , and instead of the call to new, do data.resize(len); and use tmp.data.data() to get the address of the buffer in the File.read(...) . That way, you don't need to remember to deallocate anything, because the std::vector will do it for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM