2016-09-03 15 views
1

私は自分のカスタムBattleshipゲーム用のマッチメーキングサーバーを作っています。私はネットワークコーディングの初心者ですので、あくまで疑問に思って申し訳ありません。 :PDelphi 10. TCustomWinSocketの配列使用上のアクセス違反

今すぐトピックに近い。私はデフォルトのDelphi Server/Clientソケットコンポーネントを使用します。私はパブリックセクション(clients: array of TCustomWinSocket;)で宣言された配列を持っています。メインフレームの起動時に、長さを0に設定します(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; 

は基本的に、私はこの配列を使用するたびに、それは、アクセス違反を与える

はここで例外をスローするコード例です。私はそれを得ることができません、私は配列の長さにとどまるようにコードを制限しますが、そうではありません。それともそれはいつものように私の愚かさですか?

いずれにしても、私は本当に助けをすることができます。

ありがとうございます! :)

+0

こんにちは、@KenWhite !ご回答ありがとうございます!それが問題ではなく、0要素が存在する前にプログラムをテストしていたときに、アクセス違反を起こした後、私は過去にそれを使用していたので、0のインデックスをもう一度使用しないようにしていませんでした。再び働く。私はとても混乱しています...しかし、もう一度助けてくれてありがとう! –

+0

下記の私の答えを見てください。投稿したコードにも他の問題があります。 –

答えて

4

あなたはこのループで配列の終わりを走っています。 Length(clients)は、動的配列へのインデックスがゼロから始まるため、最後のインデックスよりも1つ上位です。ループのターミネータとしてLength(clients) - 1またはHigh(clients)のいずれかを使用する必要があります。それは無効だから、

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; 

2番目のエラーがclients[0]Length(clients) = 0に割り当てるしようとしている:

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; 

はあなたにも、あなたの2番目のコードブロックで同様のエラー、プラスかなり明確だ別のものを持っていますインデックス。配列の長さがゼロの場合、配列は空であるため要素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; 
+0

もう一度ありがとう!どのように素敵なn '光沢の中のすべて! :) –

関連する問題