delphi无效的指针操作

wor*_*ace 1 delphi pointers memory-management runtime-error

这里我在delphi 7中运行了几行delphi代码:

    var
      ptr:Pointer ;
    begin
      ptr:=AllocMem(40);
      ptr:=Pchar('OneNationUnderGod');
      if ptr<>nil then
        FreeMem(ptr);
    end;
Run Code Online (Sandbox Code Playgroud)

运行此代码片段时,FreeMem(ptr)将引发错误:'无效指针操作'.如果我删除这句话:

     ptr:=Pchar('OneNationUnderGod');
Run Code Online (Sandbox Code Playgroud)

那么就不会发生错误.现在我有两个问题,

为什么会这样?2.如果我必须使用Pchar句子,我应该如何释放先前分配的内存?

非常感谢您的帮助!

Dav*_*nan 5

问题是您正在修改变量ptr中保存的地址.

您调用AllocMem来分配缓冲区,您可以使用ptr来引用该缓冲区.那很好.但是你必须永远不要改变ptr的值,即缓冲区的地址.你确实改变了它.

你写了:

ptr:=AllocMem(40);
ptr:=Pchar('OneNationUnderGod');
Run Code Online (Sandbox Code Playgroud)

第二行是问题所在.你已经修改了ptr,现在ptr引用了其他东西(在只读内存中保存的字符串文字).您现在已经忘记了通过调用AllocMem分配的缓冲区.您向AllocMem询问了新的内存块,然后立即丢弃了该内存块.

你想要做的就是复制字符串.也许是这样的:

ptr := AllocMem(40);
StrCopy(ptr, 'OneNationUnderGod');
Run Code Online (Sandbox Code Playgroud)

现在我们可以调用FreeMem,因为ptr仍然包含对AllocMem的调用所提供的地址.

ptr := AllocMem(40);
try
  StrCpy(ptr, 'OneNationUnderGod');
  // do stuff with ptr
finally
  FreeMem(ptr);
end;
Run Code Online (Sandbox Code Playgroud)

显然,在实际代码中,您会发现一种更好,更健壮的方法来指定缓冲区长度而不是硬编码值.


在您的代码中,假设应用了上述修复,ptr为nil的测试是不必要的.AllocMem永远不会返回nil.AllocMem失败导致异常被引发.


说了这么多,以这种方式操作字符串缓冲区并不常见.使用Delphi字符串是正常的.如果您需要一个PChar,例如与interop一起使用,请使用PChar(str)创建一个,其中str是string类型.

你说你必须使用动态分配的PChar缓冲区.也许就是这样,但我非常怀疑它.