2

我想使用我刚刚编写的以下函数将字符串值转换为全局内存句柄,反之亦然。

但是StrToGlobalHandle()导致我的测试程序挂起。所以GlobalHandleToStr()是不可测试的,我也想知道我的代码是否合乎逻辑。

function StrToGlobalHandle(const aText: string): HGLOBAL;
var
  ptr: PChar;
begin
  Result := 0;
  if aText <> '' then
  begin
    Result := GlobalAlloc(GMEM_MOVEABLE or GMEM_ZEROINIT, length(aText) + 1);
    if Result <> 0 then
    begin
      ptr := GlobalLock(Result);
      if Assigned(ptr) then
      begin
        StrCopy(ptr, PChar(aText));
        GlobalUnlock(Result);
      end
    end;
  end;
end;

function GlobalHandleToStr(const aHandle: HGLOBAL): string;
var
  ptrSrc: PChar;
begin
  ptrSrc := GlobalLock(aHandle);
  if Assigned(ptrSrc) then
  begin
    SetLength(Result, Length(ptrSrc));
    StrCopy(PChar(Result), ptrSrc);
    GlobalUnlock(aHandle);
  end
end;

测试代码:

procedure TForm3.Button1Click(Sender: TObject);
var
  h: HGLOBAL;
  s: string;
  s2: string;
begin
  s := 'this is a test string';
  h := StrToGlobalHandle(s);
  s2 := GlobalHandleToStr(h);
  ShowMessage(s2);
  GlobalFree(h);
end;

顺便说一句,我想使用这两个函数作为助手在程序之间发送字符串值 - 将全局句柄从进程 A 发送到进程 B,进程 B 使用GlobalHandleToStr(). BTW 2,我知道 WM_COPY 和其他 IPC 方法,这些方法不适合我的情况。

4

3 回答 3

6

Delphi 2010 中的字符串是 unicode,因此您没有分配正确的缓冲区大小。

替换这一行

Result := GlobalAlloc(GMEM_MOVEABLE or GMEM_ZEROINIT, length(aText) + 1);

有了这个

Result := GlobalAlloc(GMEM_MOVEABLE or GMEM_ZEROINIT, (length(aText) + 1)* SizeOf(Char));
于 2012-09-26T15:40:18.580 回答
3

如果您的程序在您调用 时挂起GlobalAlloc,那么您可能在程序的早期有堆损坏。这会导致未定义的行为;该函数可能会检测到问题并返回错误,它可能会使您的程序崩溃,它可能会默默地破坏您的更多内存,它可能会挂起,或者它可能会做任何其他事情。

该堆损坏可能来自先前的调用,StrToGlobalHandle因为您的StrCopy调用写入超出了分配内存的末尾。您正在分配字节,但该Length函数返回字符串中的字符数。这仅在字符为一个字节宽时才有效,而 Delphi 2009 并非如此。乘以SizeOf(Char)得到字节数:

Result := GlobalAlloc(GMEM_MOVEABLE or GMEM_ZEROINIT, SizeOf(Char) * (Length(aText) + 1));
于 2012-09-26T16:00:01.293 回答
1

您不能使用GlobalAlloc- 它仅在 16 位 Windows 中工作的程序之间发送数据。请改用内存映射文件。

于 2012-09-26T15:55:03.913 回答