如何将pascal字符串放在内存中?
我读到:http://www.freepascal.org/docs-html/ref/refsu12.html 它表示字符串存储在堆上并且引用计数。为了确定存储长度和引用的位置,我创建了一个字符串并对其进行了大量测试:
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.
第一个打印长度,第二个打印参考计数。它做得非常好,而且很有效。
现在我试图在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;
}
然后在pascal我做:
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.
pascal代码正确打印长度,并且由于赋值,引用计数增加1。这是正确的。
但是,一旦执行完毕,它就会严重崩溃!它似乎试图释放字符串/堆。如果我自己调用FreeCString,它就可以了!我不确定发生了什么。
任何想法为什么会崩溃?
答案 0 :(得分:1)
简而言之不要,以及必须的稀有情况,向pascal添加构造函数和析构函数,并通过它进行所有分配。
P.S。你可能想看看rtl / inc / astrings.inc 在Windows上的P.s.2,最容易使用COM兼容的宽带(BSTR)来处理中介语字符串类型。
答案 1 :(得分:0)
仅仅因为运行时系统在内存中以特定方式布置字符串,并不意味着编写C代码来复制该内存布局将起作用。字符串管理可能涉及其他约束或外部数据结构。要使字符串与FreePascal兼容,请使用FreePascal自己的库例程。
听起来FreePascal除了free()
之外还需要一些事情,当refcount变为零时,但如果没有一些逆向工程或深入研究ABI规范,它可能无法分辨出来。