这里我在delphi 7中运行了几行delphi代码:
var
ptr:Pointer ;
begin
ptr:=AllocMem(40);
ptr:=Pchar('OneNationUnderGod');
if ptr<>nil then
FreeMem(ptr);
end;
运行此代码段后,FreeMem(ptr)
将引发错误:'指针操作无效'。如果我删除句子:
ptr:=Pchar('OneNationUnderGod');
然后不会发生错误。现在我有两个问题,
1.为什么会发生这种情况? 2.如果我必须使用Pchar句子,我应该如何释放先前分配的内存?
非常感谢您的帮助!
答案 0 :(得分:5)
问题是您正在修改变量ptr中保存的地址。
您调用AllocMem来分配缓冲区,您可以使用ptr来引用该缓冲区。那很好。但是你必须永远不要改变ptr的值,即缓冲区的地址。而你确实改变了它。
您写道:
ptr:=AllocMem(40);
ptr:=Pchar('OneNationUnderGod');
第二行是问题所在。你已经修改了ptr,现在ptr引用了其他东西(在只读内存中保存的字符串文字)。您现在已经忘记了通过调用AllocMem分配的缓冲区。你向AllocMem询问了一个新的内存块,然后立即丢弃了那块内存。
你可能意味着要复制字符串。也许是这样的:
ptr := AllocMem(40);
StrCopy(ptr, 'OneNationUnderGod');
现在我们可以调用FreeMem,因为ptr仍然包含调用AllocMem所提供的地址。
ptr := AllocMem(40);
try
StrCpy(ptr, 'OneNationUnderGod');
// do stuff with ptr
finally
FreeMem(ptr);
end;
显然,在实际代码中,您会发现一种更好,更健壮的方法来指定缓冲区长度而不是硬编码值。
在您的代码中,假设应用了上述修复,ptr为nil的测试是不必要的。 AllocMem永远不会返回nil。 AllocMem失败导致异常被引发。
说了这么多,以这种方式操作字符串缓冲区并不常见。使用Delphi字符串是正常的。如果您需要一个PChar,例如与interop一起使用,请使用PChar(str)创建一个,其中str是string类型。
你说你必须使用动态分配的PChar缓冲区。也许就是这样,但我非常怀疑它。
答案 1 :(得分:1)
崩溃是因为您释放了未动态分配的静态内存。根本不需要释放文字所使用的内存。只有动态分配的空闲内存。
答案 2 :(得分:1)
我会尝试让你做得更明确。你似乎把变量的名称误认为是错误的。然而实际上 - 考虑到价值 - 你所做的是
ptrA:=AllocMem(40);
ptrB:=Pchar('OneNationUnderGod');
if ptrB<>nil then
FreeMem(ptrB);
每个新赋值都会更改覆盖前一个赋值的值,从而释放另一个已分配的指针。
您可以阅读StrNew,StrDispose,StrCopy,StrLCopy和示例代码等文档的文档,以查看使用PChar字符串的一些模式。