GetMem для одной переменной PChar изменить содержимое другой переменной PChar - PullRequest
1 голос
/ 21 мая 2011

Итак, у меня есть следующая проблема. У меня есть 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 ]

3 голосов
/ 22 мая 2011

Я предполагаю, что 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;
0 голосов
/ 28 июня 2011

КАК Дэвид Хеффернан Сказал до. Char - это 2 байта, а также pChar указывают на символ Unicode в Delphi 2010, но у кода Дэвида есть 2 проблемы

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

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

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

заголовок, params: PAnsiChar;

...