Delphi 10. TCustomWinSocket 数组使用时访问冲突

Delphi 10. Array of TCustomWinSocket Access violation on usage

我正在为我的自定义 Battleship 游戏制作配对服务器。我是网络编码的初学者,所以对于愚蠢的问题,我提前表示歉意。 :P

现在接近主题了。我使用默认的 Delphi Server/Client Socket 组件。我在 public 部分 (clients: array of TCustomWinSocket;) 中声明了数组,然后在主框架启动时将长度设置为零 (setLength(clients, 0);)。现在让我感到困惑的部分是:每当我尝试访问数组程序的任何元素时,都会抛出一个访问冲突异常。我已经以任何已知方式检查过,程序永远不会超过数组的长度。

下面是抛出异常的代码示例:

procedure Tmain.Button1Click(Sender: TObject);
var
i: integer;
begin
  for i := 0 to length(clients) do begin
    if assigned(clients[i]) then begin
      showmessage(IntToStr(i));
      showmessage(IntToStr(i) + ': ' + clients[i].RemoteAddress);
    end;
  end;
end;

另一个例子:

procedure Tmain.serverClientConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  addLog('(' + Socket.RemoteAddress + ':' + IntToStr(Socket.RemotePort) + ') Клиент подключился');
  if length(clients) <> 0 then begin
    showmessage(IntToStr(length(clients)));
    setLength(clients, length(clients) + 1);
    showmessage(IntToStr(length(clients)));
    clients[length(clients)] := Socket;
  end
  else if length(clients) = 0 then begin
    showmessage(IntToStr(length(clients)));
    clients[0] := Socket;
  end;

end;

基本上,每次我使用这个数组时都会出现访问冲突。搞不定,我把代码限制在数组长度内,结果不行。或者,也许是我一贯的愚蠢造成的?

无论如何,我真的需要一些帮助。

提前致谢! :)

您 运行 超出了此循环中数组的末尾。 Length(clients) 比最后一个索引高一个,因为动态数组的索引从零开始。您必须使用 Length(clients) - 1High(clients) 作为循环的终止符。

procedure Tmain.Button1Click(Sender: TObject);
var
i: integer;
begin
  for i := 0 to High(clients) do begin // or Length(clients) - 1
    if assigned(clients[i]) then begin
      showmessage(IntToStr(i));
      showmessage(IntToStr(i) + ': ' + clients[i].RemoteAddress);
    end;
  end;
end;

你的第二个代码块也有类似的错误,还有一个很清楚:

procedure Tmain.serverClientConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  addLog('(' + Socket.RemoteAddress + ':' + IntToStr(Socket.RemotePort) + ') Клиент подключился');
  if length(clients) <> 0 then begin
    showmessage(IntToStr(length(clients)));      // Need - 1 or High() here
    setLength(clients, length(clients) + 1);
    showmessage(IntToStr(length(clients)));      // Need - 1 or High() here
    clients[length(clients)] := Socket;
  end
  else if length(clients) = 0 then begin       // Second problem starts here
    showmessage(IntToStr(length(clients)));    // See text below
    clients[0] := Socket;                      
  end;                                         
end;

第二个错误是在 Length(clients) = 0 时尝试分配给 clients[0],因为这是一个无效索引。如果数组长度为零,则没有元素0,因为数组是空的——里面没有元素——一个都没有;您不能为其中包含零个元素的数组赋值。

整个块的正确代码应该是这样的 - 您不需要两个测试,测试长度 = 0,或跳过所有的箍:

procedure Tmain.ServerClientConnect(Sender: TObject; Socket; TCustomSocket);
begin
  AddLog('Whatever you want to log.');
  SetLength(clients, Length(clients) + 1);
  Clients[High(Clients)] := Socket;
end;