Delphi 一个PChar变量的GetMem更改另一个PChar变量的内容
因此,我有以下问题。我有两个PChar变量。我为第一个变量分配内存,执行一些操作,为第二个变量分配内存——在这一步中,第一个变量包含错误的值(我在调试时看到)。代码如下:Delphi 一个PChar变量的GetMem更改另一个PChar变量的内容,delphi,delphi-2010,winsock,winsock2,winsockets,Delphi,Delphi 2010,Winsock,Winsock2,Winsockets,因此,我有以下问题。我有两个PChar变量。我为第一个变量分配内存,执行一些操作,为第二个变量分配内存——在这一步中,第一个变量包含错误的值(我在调试时看到)。代码如下: procedure TReadThread.Execute; Var iRead, temp, i, count : Integer; header, params : PChar; begin try GetMem(header, 12); iRead := recv(FSocket, heade
procedure TReadThread.Execute;
Var
iRead, temp, i, count : Integer;
header, params : PChar;
begin
try
GetMem(header, 12);
iRead := recv(FSocket, header^, 12, 0);
if (iRead<>12) then
raise Exception.Create('Header recieving problem!');
temp := StrToIntDef(String(copy(header,3,4)),0);
if (temp=0) then
raise Exception.Create('Body receiving problem!');
count := temp*SizeOf(Char);
if (count+12<=16384) then
begin
GetMem(params, count);
iRead := recv(FSocket, params^, count, 0);
if (iRead<>count) then
raise Exception.Create('Cant recieve messsage fully!');
end
else
raise Exception.Create('Bad message size (>16 KB)!');
GetMem(FText, temp*SizeOf(Char)+12);
FText := PChar(String(header) + String(params));
FreeMem(header);
FreeMem(params);
except
on E : Exception do
ShowMessage(E.Message);
end;
end;
当我寻找变量头值时,我看到了一些惊人的东西,与我在过程开始时看到的不一样。如何修复它?我假定
FText
是一个PChar
。既然您说您使用的是Delphi 2010,那么您应该知道Char
实际上是WideChar
的同义词,并且是2个字节宽。我怀疑你真的想用AnsiChar
最明显的问题是为FText
分配内存,然后将其与FText
的分配一起丢弃。此外,当过程结束时,FText
引用的内存将被销毁
我认为你应该做以下几点:
- 对于
调用,切换到recv
AnsiChar
- 将
更改为FText
AnsiString
- 完全停止使用
,使用堆栈分配GetMem
procedure TReadThread.Execute;
Var
iRead, count: Integer;
header: array [0..12-1] of AnsiChar;
params: array [0..16384-1] of AnsiChar;
begin
try
iRead := recv(FSocket, header, 12, 0);
if (iRead<>12) then
raise Exception.Create('Header receiving problem!');
count := StrToIntDef(Copy(header,3,4),0);
if (count=0) then
raise Exception.Create('Body receiving problem!');
if (count+12<=16384) then
begin
iRead := recv(FSocket, params, count, 0);
if (iRead<>count) then
raise Exception.Create('Cant receive messsage fully!');
end
else
raise Exception.Create('Bad message size (>16 KB)!');
SetLength(FText, 12+count);
Move(header, FText[1], 12);
Move(params, FText[13], count);
except
on E : Exception do
ShowMessage(E.Message);
end;
end;
procedure TReadThread.Execute;
变量
iRead,计数:整数;
标头:AnsiChar的数组[0..12-1];
params:AnsiChar的数组[0..16384-1];
开始
尝试
iRead:=recv(FSocket,header,12,0);
如果(iRead12)那么
引发异常。创建('标题接收问题!');
计数:=strotintdef(复制(头,3,4),0);
如果(计数=0),则
引发异常。创建('正文接收问题!');
如David Heffernan之前所说,if(count+12。Char是2字节,并且在Delphi 2010中,pChar指向Unicode字符。但是David的代码有两个问题
如果要获取国际字符(unicode或utf8字符串),则不能使用AnsiChar
如果将params变量定义为AnsiChar的数组[0..16384-1],则您将失去程序性能。局部变量将使用堆栈并像David定义的那样定义参数,这将消耗堆栈空间
对于答案,您可以通过1个简单的更改来使用您的代码。仅将header和params变量定义为PAnsiChar。您可以将其他代码保持不变
header,params:PAnsiChar;你不想让PChar成为PAnsiChar吗?并用SizeOf(AnsiChar)
替换SizeOf(AnsiChar)
?这一更改的目的是什么?AnsiChar只占用1个字节,Delphi2010中的Char占用2个字节。请看下面的答案。我看不出在“GetMem”上更改“header”的任何原因(params,count);”。我看到的唯一明显的问题是David指出的一个问题,即每次调用时FText泄漏内存+保持一个悬空指针。我在线程的析构函数中使用FreeMem(FText)。+1表示不再使用getmem。请注意,您还可以使用:var header:ansistring;begin SetLength(header,12);
创建一个长度为12的字符串,该字符串在退出例程时自动销毁。鉴于堆栈为1MB,创建一个16KB的变量看起来是一个很好的解决方案。
procedure TReadThread.Execute;
Var
iRead, count: Integer;
header: array [0..12-1] of AnsiChar;
params: array [0..16384-1] of AnsiChar;
begin
try
iRead := recv(FSocket, header, 12, 0);
if (iRead<>12) then
raise Exception.Create('Header receiving problem!');
count := StrToIntDef(Copy(header,3,4),0);
if (count=0) then
raise Exception.Create('Body receiving problem!');
if (count+12<=16384) then
begin
iRead := recv(FSocket, params, count, 0);
if (iRead<>count) then
raise Exception.Create('Cant receive messsage fully!');
end
else
raise Exception.Create('Bad message size (>16 KB)!');
SetLength(FText, 12+count);
Move(header, FText[1], 12);
Move(params, FText[13], count);
except
on E : Exception do
ShowMessage(E.Message);
end;
end;