Недопустимая операция с указателем PChar при StrPLCopy

#delphi #delphi-2010 #winsock #winsock2 #winsockets

#delphi #delphi-2010 #winsock #winsock2 #winsockets

Вопрос:

Я пишу какой-нибудь TCP-сервер, использующий WinSock 2, и у меня есть процедура, которая улавливает событие FD_READ. В этой процедуре мне нужно проанализировать полученное сообщение. Код находится здесь:

 procedure TfrmMain.WndProc_OnWSANetEvent(var Msg: TMessage);
Var
  iCurrThread, n : Integer;
  i : Integer;
  temp : PChar;
  len : Integer;
  params : PChar;
  username : PChar; password : PChar;
  ind : Integer;
  tempy : PChar;
  tempn : PChar;
begin
  case WSAGetSelectEvent(Msg.LParam) of
    FD_READ :
      while True do
      begin
        if (FreeRThreads.GetCount <> 0) then
          begin
            iCurrThread := FreeRThreads.Pop;
            if (ReadThreads[iCurrThread].Terminated) then
              begin
                ReadThreads[iCurrThread].SetFSocket(Msg.WParam);
                ReadThreads[iCurrThread].Execute;

                temp := ReadThreads[iCurrThread].GetFText;
                meLog.Lines.Add(temp);

                if (copy(temp,1,2)='AU') then
                  begin
                    StrPLCopy(params, PChar(copy(temp, 7, StrToInt( copy(temp, 3, 4) ) )), 16372);
                    ind := pos(' ', params);
                    StrPLCopy(username, PChar(copy(params, 1, ind-1)), 16372);
                    StrPLCopy(password, PChar(copy(params, ind   1, StrLen(params))), 16372);

                    StrPLCopy(tempy, PChar('AU0001y'), 14);
                    StrPLCopy(tempn, PChar('AU0001n'), 14);

                    if (username=PChar('dizpers')) then
                      if (password=PChar('admin')) then
                        send(Msg.WParam, tempy^, 14, 0)
                      else
                        send(Msg.WParam, tempn^, 14, 0)
                    else
                      send(Msg.WParam, tempn^, 14, 0);

                    meLog.Lines.Add('USER = ' username);
                    meLog.Lines.Add('PASSWORD = ' password);
                  end;



                FreeRThreads.Push(iCurrThread);
                break;
              end;
          end;
      end;
    FD_CLOSE :
      begin
        n := CSocketsCount - 1;
        for i := 0 to n do
          if (ClientSockets[i] = Msg.WParam) then
            begin
              closesocket(ClientSockets[i]);
              FreeSockets.Push(i);
              break;
            end;
      end;
  end;
end;
  

Во время отладки у меня происходит «Нарушение доступа… запись адреса …» в строке

 StrPLCopy(params, PChar(copy(temp, 7, StrToInt( copy(temp, 3, 4) ) )), 16372);
  

Пожалуйста, помогите мне решить эту проблему и понять, почему это произошло. TIA!

Комментарии:

1. Есть ли причина, по которой вы не использовали набор компонентов TCP, такой как Indy (или другие)?

Ответ №1:

Вы должны выделить память для params переменной перед использованием StrPLCopy (то же самое относится к username , password , tempy , tempn )

проверьте этот пример

 Var
  Dest   : PChar;
  Source : PChar;
begin
    Source:='This is a buffer to copy';
    //alloc a buffer of 1024 bytes 
    GetMem(Dest,1024);
    try
      //copy 
      StrPLCopy(Dest, Source, Length(Source));
      //do something
      Writeln(Dest);
    finally
      //free the memory
      FreeMem(Dest);
    end;
end;
  

Комментарии:

1. Спасибо! Пример работает нормально. Но теперь у меня есть другой вопрос. Я знаю размер памяти, который мне нужно выделить, но о других переменных PChar я знаю только, что их длина должна быть не более 16372. Итак, у кого я могу получить память для переменной, если я не знаю размер?

2. @dizpers пожалуйста, задайте это как новый вопрос с некоторыми дополнительными деталями

3. Объявите переменную как array[0..16371] of Char , что также устраняет явное выделение памяти.