64bit Windows Issues

https://attnam.com/topics/64bit-Windows-Issues

The Cathedral of Attnam > IVAN Development

#1 Jul 30, 2016, 6:34 pm Hide

orange

Is anyone aware of any issues in the FeLib area which causes 64bit MinGW builds to appcrash on startup?

Some background...

https://attnam.com/posts/24620
https://attnam.com/topics/Patch-for-crash-on-linux-64-bit

I find that the game tries to delete a char array when importing the char.dat file. Specifically the line: "@Dd says sadly: \"Back then I used to love bananas. One day the master guard slipped on a peel I'd dropped. Guess where I got transferred?\"",

Seems to stop and crash after 128 chars, if I change the length of this string to be less than 128 chars, it doesn't seem to crash anymore, but the next string entry > 128 chars does.

Is there any known limitation to the Felibstring 128 chars?
#2 Jul 30, 2016, 10:30 pm Hide

orange

I have traced the error to this:

#define REFS(ptr) reinterpret_cast<ulong*>(ptr)[-1]

void festring::SlowAppend(char Char)
DeletePtr = &REFS(OldPtr);

    if(DeletePtr)
      delete [] (DeletePtr);


Explanation: When reading in a string, the festring allocates memory in 128 byte chunks. If say there is an attempt to append an additional character to a string which is already 128 bytes in length, there is a new memory allocation and a deallocation (delete) of the old memory.

When allocating a new string,

    Size = 1;
    Reserved = FESTRING_PAGE;
    char* Ptr = sizeof(int*) + new char[FESTRING_PAGE + sizeof(int*) + 1];
    REFS(Ptr) = 0;
    Ptr[0] = Char;
    Data = Ptr;

You can see that Data is actually an offset the size of int*.
When deallocation occurs, it needs to reference the original pointer that the new operator returned.

This is currently done using:

#define REFS(ptr) reinterpret_cast<ulong*>(ptr)[-1]

void festring::SlowAppend(char Char)
DeletePtr = &REFS(OldPtr);

    if(DeletePtr)
      delete [] (DeletePtr);


Here you can see the DeletePtr is equal to the <ulong*>Data[-1]. However remember we need to offset the DeletePtr back by sizeof(int*), which is 8 in 64bit system or 4 in a 32bit in order for this to work.

The error occurs because REFS references <ulong*>&Data[-1], and since is casts Data as a ulong which is an unsigned long 32bits, it only moves the pointer back 4 bits. While this works in a 32bit system, the 64bit system will fail to perform the delete [] operation as the DeletePtr needs to actually reference <ulong*>&Data[-2].

I have done a 'quick' fix which changes the memory allocation from.
char* Ptr = sizeof(int*) + new char[FESTRING_PAGE + sizeof(int*) + 1];
to
char* Ptr = sizeof(int) + new char[FESTRING_PAGE + sizeof(int) + 1];






#3 Jul 31, 2016, 12:00 am Hide

fejoa

Looks like an elderly part of the original code.

orange wrote
I have done a 'quick' fix which changes the memory allocation from.
char* Ptr = sizeof(int*) + new char[FESTRING_PAGE + sizeof(int*) + 1];
to
char* Ptr = sizeof(int) + new char[FESTRING_PAGE + sizeof(int) + 1];

Do you know of any possible limitations to this fix? If not, then just chuck it on the git repo