我想使用我刚刚编写的以下函数将字符串值转换为全局内存句柄,反之亦然。
但是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;
BTW,我想使用这两个函数作为帮助程序在程序之间发送字符串值 - 从进程A向进程B发送全局句柄,进程B使用GlobalHandleToStr()
获取字符串。
BTW 2,我知道WM_COPY和其他IPC方法,那些不适合我的情况。
答案 0 :(得分: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));
答案 1 :(得分:3)
如果您的程序在致电GlobalAlloc
时挂起,那么您的程序中可能存在堆损坏。这会导致不确定的行为;该函数可能会检测到问题并返回错误,它可能会使程序崩溃,它可能会默默地损坏您的内存,可能会挂起,或者它可能会执行任何其他操作。
该堆损坏可能来自先前对StrToGlobalHandle
的调用,因为您的StrCopy
调用超出了已分配内存的末尾。您正在分配字节,但Length
函数返回字符串中字符的数量。这仅在字符宽度为1个字节时有效,而Delphi 2009则不然。乘以SizeOf(Char)
得到字节数:
Result := GlobalAlloc(GMEM_MOVEABLE or GMEM_ZEROINIT, SizeOf(Char) * (Length(aText) + 1));
答案 2 :(得分:1)
您无法使用GlobalAlloc
在程序之间发送数据 - 它仅适用于16位Windows。改为使用内存映射文件。