Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 一个PChar变量的GetMem更改另一个PChar变量的内容_Delphi_Delphi 2010_Winsock_Winsock2_Winsockets - Fatal编程技术网

Delphi 一个PChar变量的GetMem更改另一个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

因此,我有以下问题。我有两个PChar变量。我为第一个变量分配内存,执行一些操作,为第二个变量分配内存——在这一步中,第一个变量包含错误的值(我在调试时看到)。代码如下:

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;