How are pascal strings laid out in memory?
I read: http://www.freepascal.org/docs-html/ref/refsu12.html It says that strings are stored on the heap and reference counted. To figure out where the length and reference was stored, I created a string and did tests on it a lot:
type PInt = ^Integer;
var
str: String;
begin
str := 'hello';
writeln(PInt(@str[1]) - (sizeof(integer) * 1)); //length
writeln(PInt(@str[1]) - (sizeof(integer) * 2)); //reference count
end.
The first one prints the length and the second one prints the reference count. It does this perfectly fine and it works.
Now I tried to emulate the same thing in C:
Export char* NewCString()
{
const char* hello_ptr = "hello";
int length = strlen(hello_ptr);
//allocate space on the heap for: sizeof(refcount) + sizeof(int) + strlength
char* pascal_string = (char*)malloc((sizeof(int) * 2) + length);
*((int*)&pascal_string[0]) = 0; //reference count to 0.
*((int*)&pascal_string[sizeof(int)]) = length; //length of the string.
strcpy(&pascal_string[sizeof(int) * 2], hello_ptr); //copy hello to the pascal string.
return &pascal_string[sizeof(int) * 2]; //return a pointer to the data.
}
Export void FreeCString(char* &ptr)
{
int data_offset = sizeof(int) * 2;
free(ptr - data_offset);
ptr = NULL;
}
Then in pascal I do:
var
str: string;
begin
str := string(NewCString());
writeln(PInt(@str[1]) - (sizeof(integer) * 1)); //length - prints 5. correct.
writeln(PInt(@str[1]) - (sizeof(integer) * 2)); //reference count - prints 1! correct.
//FreeCString(str); //works fine if I call this..
end.
The pascal code prints the length correctly and the reference count is increased by one due to the assignment. This is correct.
However, as soon as it is finished executing, it crashes badly! It seems to be trying to free the string/heap. If I call FreeCString myself, it works just fine! I'm not sure what is going on.
Any ideas why it crashes?