在Delphi字符串复制之前需要分配内存吗?

在Delphi字符串复制之前需要分配内存吗?,delphi,string,memory-management,Delphi,String,Memory Management,执行Delphi字符串复制时是否需要分配内存 我有一个函数,可以将Windows消息发布到应用程序中的另一个窗体。它看起来像这样: // Note: PThreadMessage = ^TThreadMessage; TThreadMessage = String; function PostMyMessage( aStr : string ); var gMsgPtr : PThreadMessage; gStrLen : Integer; begin New(gMsgPtr)

执行Delphi字符串复制时是否需要分配内存

我有一个函数,可以将Windows消息发布到应用程序中的另一个窗体。它看起来像这样:

// Note:  PThreadMessage = ^TThreadMessage; TThreadMessage = String;

function PostMyMessage( aStr : string );
var
  gMsgPtr : PThreadMessage;
  gStrLen : Integer;
begin
  New(gMsgPtr);
  gStrLen := StrLen(PWideChar(aMsg));
  gMsgPtr^ := Copy(aMsg, 0, gStrLen);
  PostMessage(ParentHandle, WM_LOGFILE, aLevel, Integer(gMsgPtr));

  // Prevent Delphi from freeing this memory before consumed.
  LParam(gMsgPtr) := 0;
end;

您不需要分配内存来复制字符串,但在这种情况下,您不希望传递指向Delphi字符串的指针。您希望传递一个PChar(也称为C字符串),并且必须为此分配内存。

您不需要分配任何内存。事实上,您甚至不需要调用
Copy
。一个简单的字符串赋值就足够了;引用计数将在多个线程中正确跟踪。您也不需要清除
gMsgPtr
;由于它不是
string
类型的变量,编译器不会为它插入任何清理代码

begin
  New(gMsgPtr);
  gMsgPtr^ := aMsg;
  PostMessage(ParentHandle, wm_LogFile, aLevel, LParam(gMsgPtr));
end;

如果仍要调用
Copy
,则无需首先计算长度。它将自动将索引参数钳制到允许的最大范围。当您想要请求“字符串的其余部分”时,只需将
MaxInt
作为第三个参数传递,
Copy
就会知道该怎么做。对于第二个参数,它也会这样做,自动将任何值增加到至少1,即最低有效字符索引。

我肯定遗漏了什么。将aMsg分配给gMsgPtr会增加字符串的引用计数。执行PostMessage后,引用计数将递减。消息的methodhandler最终执行时,LPRAM中传递的字符串不再指向有效内存(aka已被释放),这难道不可能吗?@Lieven,在进入此函数时,引用计数必须至少为1(对于
aMsg
中保存的引用)。对
gMsgPtr^
的赋值添加了一个引用,因此现在它至少是2。当此函数返回时,
aMsg
中的引用消失,但由于
gMsgPtr^
的原因,计数仍然至少为1。当消息处理程序运行时,它将调用
Dispose(PThreadMessage(lParam))
,引用计数将再次递减,可能会释放字符串。此处显示的代码不能释放
gMsgPtr
;该内存的所有权将转移给邮件的收件人。我明白了。我没有考虑将变量声明为PThreadMessage io TThreadMessage这一事实。谢谢你的解释。