1

Je crée un serveur Matchmaking pour mon jeu Battleship personnalisé. Je suis un débutant au codage réseau, donc je suis désolé d'avance pour les questions stupides. : PDelphi 10. Tableau de violation d'accès TCustomWinSocket sur l'utilisation

Maintenant plus proche du sujet. J'utilise le composant Delphi Server/Client Socket par défaut. J'ai mon tableau déclaré dans la section publique (clients: array of TCustomWinSocket;), puis sur le démarrage de l'image principale, j'ai mis la longueur à zéro (setLength(clients, 0);). Maintenant, la partie confuse pour moi: chaque fois que j'essaie d'accéder à un élément du programme de tableau lance une exception de violation d'accès. J'ai vérifié de toute façon connue, le programme ne dépasse JAMAIS la longueur du tableau.

Voici exemple de code qui génère une exception:

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; 

Un autre exemple:

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; 

En fait, chaque fois que j'utilise ce tableau il donne une violation d'accès. Je ne peux pas l'obtenir, je limite le code pour rester dans la longueur du tableau, mais ce n'est pas le cas. Ou, peut-être, c'est comme d'habitude ma stupidité qui l'a causé?

De toute façon, je pourrais vraiment utiliser de l'aide.

Merci d'avance! :)

+0

Bonjour, @KenWhite ! Merci de répondre! Quand je testais le programme avant que ce n'était pas le problème et que l'élément 0 existait, après avoir lancé la violation d'accès, je n'ai pas essayé d'utiliser de nouveau l'index, parce que je l'ai déjà utilisé, fonctionne à nouveau. Je suis tellement confus ... Mais merci encore pour l'aide! –

+0

Voir ma réponse ci-dessous; vous avez d'autres problèmes avec le code que vous avez publié. –

Répondre

4

Vous exécutez la fin de la matrice dans cette boucle. Length(clients) est un plus haut que le dernier index, car l'index dans un tableau dynamique commence à zéro. Vous devez soit utiliser Length(clients) - 1 ou High(clients) comme terminateur de votre boucle.

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; 

Vous avez une erreur semblable dans votre deuxième bloc de code ainsi, plus une autre qui est assez clair:

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; 

La deuxième erreur tente d'attribuer à clients[0] quand Length(clients) = 0, parce que c'est invalide indice. Si la longueur du tableau est zéro, il n'y a pas d'élément 0, car le tableau est vide - il n'y a aucun élément - pas un seul; vous ne pouvez pas affecter une valeur à un tableau qui contient zéro élément.

Le code approprié pour ce bloc entier serait quelque chose comme ça - vous n'avez pas besoin à la fois des tests pour tester la longueur = 0, ou de sauter à travers tous les cerceaux:

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

Merci encore! Comme tout est beau et brillant! :) –