Different data size in release/debug? (c++)

Started by
12 comments, last by Zakwayda 5 years, 6 months ago

Hi!

I save/load my game data as binary files using fwrite() and fread(). I save large blocks of data by using: "fwrite(&item->startSave,1,&item->endSave-&item->startSave,f);" on my classes. This might be primitive but it has worked very well for me for many years.

However:
I now realise (with a new version of the IDE and some other upgrades) there seem to be something not working well when loading data (the binary file) in release mode (the data was saved in debug mode and loads well from there). At first it loads fine some classes but some data later on in the load function seems to be corrupt.

Is the size of the variables (arrays of ints and so on) changing between debug and release and can this be the problem? Some memory padding or something? Im using visual studio 2017 (c++) if that matters.

Thank you!

Advertisement

Remember the sizeof() a struct/class includes some things you're not supposed to reason about as a user of the language, such as the VTable if the type (or any of its supertypes) have any virtual methods.

You may need to re-do your serialization from scratch. If you are going to use C-isms like fwrite() and fread(), which means casting to/from void pointers, you must restrict yourself to serializing only structs/classes which contain no pointers, and have no virtual methods.

RIP GameDev.net: launched 2 unusably-broken forum engines in as many years, and now has ceased operating as a forum at all, happy to remain naught but an advertising platform with an attached social media presense, headed by a staff who by their own admission have no idea what their userbase wants or expects.Here's to the good times; shame they exist in the past.

You should probably search for info about data aligning/packing and how the compiler handles this stuff.

I only save sections of data that includes no pointers. See example below (only saves stuff between saveStart and saveEnd). So given that, it still means it can only work in debug mode? So the size of these ints and floats are different in debug and release mode?


class myClass{
public:

bool saveStart;

int something[10];
float mass;
float height;
char name[200];

bool saveEnd;

int notSavedData;

void doStuff();
int getMass();

};

 

4 hours ago, suliman said:

 

Is the size of the variables (arrays of ints and so on) changing between debug and release and can this be the problem? Some memory padding or something? Im using visual studio 2017 (c++) if that matters.

An array if integers in debug is the same size as it is in release.  The differences between debug and release will depend on optimization settings for things like alignment, which will affect the in-memory size of user defined structs and arrays of those structs.

Can you include your entire load/save code?

If you're curious, there may be ways of examining the layout. Maybe there's something available in your development environment. Or, you could examine the output files in a hex editor, or compute and log the differences between the addresses of each member of interest and 'saveStart' (as e.g. char *'s). By comparing results in debug and release, you might be able to identify where and why things are going wrong.

It seems like it could be interesting and perhaps informative to figure that out, but as has been mentioned, this approach has various caveats associated with it, so it might be worth at least considering alternative approaches.

Quote

(only saves stuff between saveStart and saveEnd)

Well, do some analysis yourself. Make a test program which emits the sizeof(), the address, the relative address of ::saveStart and the relative address of ::saveEnd... and compare the output in debug and release builds. And if they come out identical... be sure to post your test-program's code when you post your results here.

RIP GameDev.net: launched 2 unusably-broken forum engines in as many years, and now has ceased operating as a forum at all, happy to remain naught but an advertising platform with an attached social media presense, headed by a staff who by their own admission have no idea what their userbase wants or expects.Here's to the good times; shame they exist in the past.

IMO if you're having this kind of problem your serialization is broken. You should never assume a given class object layout in memory. You don't control it, the compiler does. Write each data member on it's own.

I found I had included something that wasnt strictly primitive data in my saved data-range...

This seem to work fine in debug mode but not in release (maybe debug allows some errors, or "fixes" the errors trying to be helpful but instead masking a problem i actually had all along).

Those save/load ranges that did only (truely) include primitive data worked well even in release build.

13 hours ago, suliman said:

I found I had included something that wasnt strictly primitive data in my saved data-range...

This seem to work fine in debug mode but not in release (maybe debug allows some errors, or "fixes" the errors trying to be helpful but instead masking a problem i actually had all along).

Those save/load ranges that did only (truely) include primitive data worked well even in release build.

What did you include?  Also, if what you were actually saving was different from what you posted above, why did you post it?

This topic is closed to new replies.

Advertisement