1

So, this PhysFS class I'm writing seems to be corrupting the first few characters of all the data it reads. The rest of the data seems fine...

Here is the code being called:

std::vector<uint8_t> FileIO::vectorFromFile(std::string fileName)
{
    auto buffer = std::make_shared<std::vector<uint8_t> > (*new std::vector<uint8_t>);
    if(PHYSFS_exists(fileName.c_str()))
    {
        PHYSFS_File* filenameHandle = PHYSFS_openRead(fileName.c_str());
        if (filenameHandle != 0)
        {
            bufferSize = PHYSFS_fileLength(filenameHandle);
            buffer->resize(bufferSize);
            PHYSFS_read (filenameHandle, &buffer->front(), sizeof(uint8_t), bufferSize);
            PHYSFS_close(filenameHandle);
        }
    }
    else
    {
        std::cerr << fileName << " doesn't exist.";
    }
    buffer->push_back((uint8_t) '\0');
    return *buffer;
}

SimpleFile FileIO::getSimpleFile(std::string fileName)
{
    SimpleFile file;
    std::vector<uint8_t> dataVector = vectorFromFile(fileName);
    file.data = &(dataVector[0]);
    file.sizeInBytes = dataVector.size();

    return file;
}

And this example outputs:

─ s  9c rsion="1.0" encoding="UTF-8"?>
<map version="1.0" orientation="orthogonal" width="40" height="40" tilewidth="32
" tileheight="32">
 <tileset firstgid="1" name="Desert" tilewidth="32" tileheight

When it should be:

<?xml version="1.0" encoding="UTF-8"?>
<map version="1.0" orientation="orthogonal" width="40" height="40" tilewidth="32"
tileheight="32">
 <tileset firstgid="1" name="Desert" tilewidth="32" tileheight

Sorry about the pastebin.

I'm a bit new to reading from filesystems and PhysFS, so forgive me if I made an obvious mistake.

EDIT: The header:

#ifndef FILEIO_H
#define FILEIO_H

#include <string>
#include <vector>

struct SimpleFile;

class FileIO
{
private:
    int bufferSize = 0;
public:
    FileIO();
    ~FileIO();
    std::vector<uint8_t> vectorFromFile(std::string fileName);
    SimpleFile getSimpleFile(std::string fileName);
};

struct SimpleFile
{
    uint8_t* data;
    int sizeInBytes;
};

#endif // FILEIO_H
user1834037
  • 65
  • 1
  • 5

1 Answers1

1

I think your data is just going out of scope and being reused for something else:

SimpleFile FileIO::getSimpleFile(std::string fileName)
{
    SimpleFile file;
    std::vector<uint8_t> dataVector = vectorFromFile(fileName);
    file.data = &(dataVector[0]);
    file.sizeInBytes = dataVector.size();
    return file;
}

Once the function returns dataVector is gone so file.data is an invalid pointer. Of course I do not know much about the C++11 new features that could override that.

Abdul Rahman
  • 2,097
  • 4
  • 28
  • 36
Indy
  • 26
  • 1
  • Hmm, yeah, that's probably it. I just now though, thanks to a mailing list suggestion, replaced the vector with plain memory (a new[] uint8_t array). I was ignoring the KISS principle, basically, by using a vector instead of an array. Extreme props anyway. – user1834037 Nov 21 '12 at 00:58
  • @user1834037: Of course, if your `SimpleFile` actually *stored* a `std::vector` instead of returning a memory-leak-prone array of `uint8_t`s, none of that would be needed. At the very least, you should be using a `std::unique_ptr` to manage the memory so you don't get a leak. Using `std::vector` *is* simple; you made it complicated by not using it everywhere you use an array. – Nicol Bolas Nov 21 '12 at 01:10
  • *Headdesk* Right, so I've changed it back to a vector, but on the stack in a SimpleFile instead of the heap. It works and it's safer, so thanks. – user1834037 Nov 21 '12 at 20:36