News:

11 March 2016 - Forum Rules

Main Menu

(C++) Vector corruption?

Started by doop, June 06, 2011, 11:16:52 AM

Previous topic - Next topic

doop

I've been working on a game engine for the past couple months, and have recently been working on porting it via devkitPPC to the Wii so the engine can have its' platform specifics abstracted away so it can be ported to any platform.

I've run into an issue with a vector inside a filesystem object I'm using to store my VFS's file indexes, all of the fields now fill fine (used to fail on this due to endianess issues which I fixed), but after leaving the function to load all the data, and closing the ifstream, when returning to the filesystem object to load a file, when it accesses the vector again, the file count's decreased from 5 to 2, and the filenames are corrupt and don't display via printf like they do before leaving that function call.

It's declared as:
vector<FSHeader *> Filesystem;
In the filesystem object's header, and I literally just push_back objects onto it. The code works 100% pefectly on Windows and Linux, but seems to fail when running inside Dolphin. Could this be some kind of emulation issue?

Gemini

Is FSHeader a structure or a class? If it's the second case, please post the constructor/destructor for it and the code used to push it back.

doop

It's a struct:

struct FSHeader {
char *filename;
Uint32 length;
Uint8 unpackType;
Uint32 uncomplength;
Uint64 dataposition;
};


The code I use to create and push_back each one is the following:
FSHeader *currentFile = new FSHeader;
Filesystem.push_back(currentFile);


I'm just not sure why it's corrupting on the Wii and not on the PC, the only difference between the two platforms' code is I swap the bytes to correct the endianess for the structs' values like this:

//Read in File Length
fileStream.read(reinterpret_cast<char *>(&currentFile->length), sizeof(currentFile->length));
//Swap bytes
ByteSwap5(currentFile->length);


ByteSwap5 in turn does this:
#define ByteSwap5(x) ByteSwap((unsigned char *) &x,sizeof(x))

void ByteSwap(unsigned char * b, int n)
{
   register int i = 0;
   register int j = n-1;
   while (i<j)
   {
      std::swap(b[i], b[j]);
      i++, j--;
   }
}

Gemini

In that case you don't really need to make that vector use pointers as attributes. You can simply declare it as vector<FSHeader> Filesystem, push an empty FSHeader structure without the new operator, and be fine with any corruption issues, unless you're programming it to use pointers for a specific reason I can't see from those brief snippets of code (which look totally fine to me, by the way).

doop

#4
The only reason I used pointers is for some reason in my early tests if I didn't create it via New, when making another struct in the loop it'd be like it was pointing to the previous struct, as all of its' values were there. I may of been confused or using bad testing data though.

[edit]

From what Tauwasser's told me and from my own findings it seems my problem was a twofold thing.

Firstly, as I was using a struct the sizeof call would report invalid lengths due to the padding some compilers use to ensure all variables are aligned in memory, so I changed it to a class to get around this.

Secondly, I found out something I didn't know about before about functions - when you create variables inside a function call, that call has its' own stack which the variables are created on, which is destroyed when you return, so any variables created are destroyed at the end. I was storing the filename of the VFS into a new variable, and creating my Filesystem vector in my initializer, so this was causing the main bug, which I fixed by making the variables static.

I'm guessing the devkitppc compiler is stricter than the VC++ compiler, it's strange how bog standard gcc seems to be as liberal as VC++, yet devkitppc's modified gcc is anal about this kinda stuff.

Thanks for the help guys :thumbsup: