2011-05-21 58 views
1

所以,我有以下問題。我有2個PChar變量。我首先分配內存,做一些操作,爲第二個變量分配內存 - 在這一步中,第一個變量包含錯誤值(我在調試時看到它)。下面是代碼:GetMem爲一個PChar變量其他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; 

上線

iRead := recv(FSocket, params^, count, 0); 

當我尋找變量標頭值 - 我看到somethind驚人的 - 不是當我在程序的開頭看到的一樣。我如何解決它?

+0

難道你不想讓PChar成爲PAnsiChar?並用'SizeOf(AnsiChar)'替換'SizeOf(Char)'? – Johan 2011-05-21 20:14:41

+0

和這個改變的目的是什麼? – dizpers 2011-05-21 20:20:29

+1

Ansichar只佔用1個字節,Delphi2010中的Char佔用2個字節。請參閱下面的答案。 – Johan 2011-05-21 20:48:29

回答

3

我推測FTextPChar。既然你說你使用的是Delphi 2010,你應該知道Char實際上是WideChar的同義詞,並且是2個字節寬。我懷疑你真的想要使用AnsiChar

最明顯的問題是,您爲FText分配內存,然後將其丟棄,並將其分配給FText。更重要的是,FText所指的內存在程序結束時被破壞。

我認爲,你應該做到以下幾點:

  • 切換到AnsiCharrecv電話。
  • 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; 
+2

+1不再使用getmem。請注意,您也可以使用:'var header:ansistring;開始SetLength(header,12);'創建一個長度爲12的字符串,該字符串在退出例程時被自動銷燬。鑑於堆棧爲1MB的事實,創建一個16KB的var看起來像是一個很好的解決方案。 – Johan 2011-05-21 20:51:13

0

大衛·赫弗南說befor。字符爲2個字節,也PCHAR點在2010年德爾福一個Unicode字符,但大衛的代碼有2個問題

  1. 如果你想獲得國際字符(Unicode或UTF8字符串),你不能使用AnsiChar

  2. 如果將params變量定義爲AnsiChar的Array [0..16384-1],那麼您將失去程序性能。局部變量將使用堆棧並像David定義的那樣定義參數,這會消耗堆棧空間。

爲您可以使用的答案使用您的代碼通過1個簡單的更改。只將你的頭和params變量定義爲PAnsiChar。您可以將其他代碼保持不變。

header,params:PAnsiChar;