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 проблемы.

  1. Если вы хотите получить международные символы (строки Unicode или UTF8), вы не можете использовать AnsiChar

  2. Если определить переменную params как Array [0..16384-1] из AnsiChar, то вы потеряете производительность вашей программы. локальные переменные будут использовать стек и определять параметры, как определил Дэвид, и будет занимать ваше пространство стека.

Для ответа вы можете использовать свой код путем 1 простого изменения. только определите вашу переменную header и params как PAnsiChar. Вы можете поставить другие коды без изменений.

заголовок, параметры: PAnsiChar;

Другие вопросы по тегам