GetMem для одной переменной PChar изменяет содержимое другой переменной PChar
Итак, у меня есть следующая проблема. У меня есть 2 переменные 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);
Когда я искал значение переменной HEADER - я увидел нечто удивительное - не то же самое, что и в начале процедуры. Как я могу это исправить?
2 ответа
Я предполагаю что FText
это PChar
, Поскольку вы говорите, что используете Delphi 2010, вы должны знать, что Char
на самом деле является синонимом WideChar
и имеет ширину 2 байта. Я подозреваю, что вы действительно хотите использовать AnsiChar
,
Наиболее явная проблема заключается в том, что вы выделяете память для FText
а затем отказаться от него с назначением FText
, Более того, память, которая FText
ссылка уничтожается, когда процедура заканчивается.
Я думаю, что вы, вероятно, должны сделать следующее:
- Переключиться на
AnsiChar
дляrecv
звонки. - + Изменить
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;
А.С. Дэвид Хеффернан сказал перед. Char - это 2 байта, а также pChar указывают на символ Unicode в Delphi 2010. Но у кода Дэвида есть 2 проблемы.
Если вы хотите получить международные символы (строки Unicode или UTF8), вы не можете использовать AnsiChar
Если определить переменную params как Array [0..16384-1] из AnsiChar, то вы потеряете производительность вашей программы. локальные переменные будут использовать стек и определять параметры, как определил Дэвид, и будет занимать ваше пространство стека.
Для ответа вы можете использовать свой код путем 1 простого изменения. только определите вашу переменную header и params как PAnsiChar. Вы можете поставить другие коды без изменений.
заголовок, параметры: PAnsiChar;