IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Delphi Discussion :

[Problème] Erreur avec un Tableau dynamique dans un record


Sujet :

Delphi

  1. #1
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 13
    Points : 7
    Points
    7
    Par défaut [Problème] Erreur avec un Tableau dynamique dans un record
    Bonsoir,

    Je poste ici pour demander un peu d'aide car je suis vraiment bloqué par un problème que je n'arrive pas à résoudre ... Je m'explique : j'ai crée un record comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    Type
       T_CMD_AUTH_LOGON_CHALLENGE = packed Record
          Opcode          : byte;
          Error           : byte;
          Size            : word;
          GameName        : array [0..3] of byte;
          Gameversion     : array [0..2] of byte;
          GameBuild       : word;
          Platform        : array [0..3] of byte;
          OperatingSystem : array [0..3] of byte;
          Area            : array [0..3] of byte;
          TimeZone        : Cardinal;
          ClientIP        : array [0..3] of byte;
          AccoutNameLen   : byte;
          AccountName     : array of byte;
       end;
    Donc le champ AccountName est un tableau dynamique apres je complète tout ca grace a ma procedure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    Procedure Send_CMD_AUTH_LOGON_CHALLENGE;
    Var
       CMD_AUTH_LOGON_CHALLENGE : T_CMD_AUTH_LOGON_CHALLENGE;
       PacketSize : word;
       i : word;
       lst : TStringList;
    Begin
       CMD_AUTH_LOGON_CHALLENGE.Opcode := 0;
       CMD_AUTH_LOGON_CHALLENGE.Error := 3;
       PacketSize := (SizeOf(CMD_AUTH_LOGON_CHALLENGE)-SizeOf(CMD_AUTH_LOGON_CHALLENGE.AccountName))+length(AccountName);
       CMD_AUTH_LOGON_CHALLENGE.Size := PacketSize-(4);
       Fill_array(CMD_AUTH_LOGON_CHALLENGE.GameName, 'WoW', true);
       lst := TStringList.Create;
       lst.Text:= Game_Version;
       lst.text := StringReplace(lst.text,'.',#13#10,[rfReplaceAll]);
       for i:=0 to lst.count-1 do begin
          CMD_AUTH_LOGON_CHALLENGE.Gameversion[i]:=StrToInt(lst.Strings[i]);
       end;
       CMD_AUTH_LOGON_CHALLENGE.GameBuild := Game_Build;
       Fill_array(CMD_AUTH_LOGON_CHALLENGE.Platform, 'x86', true);
       Fill_array(CMD_AUTH_LOGON_CHALLENGE.OperatingSystem, 'Win', true);
       Fill_array(CMD_AUTH_LOGON_CHALLENGE.Area, 'frFR', true);
       CMD_AUTH_LOGON_CHALLENGE.TimeZone := 60;
       Local_IP := GStack.LocalAddress;
       lst.Text:= Local_IP;
       lst.Text := StringReplace(lst.text,'.',#13#10,[rfReplaceAll]);
       for i:=0 to lst.count-1 do begin
          CMD_AUTH_LOGON_CHALLENGE.ClientIP[i] := StrToInt(lst.Strings[i])
       end;
       SetLength(CMD_AUTH_LOGON_CHALLENGE.AccountName, length(AccountName));
       CMD_AUTH_LOGON_CHALLENGE.AccoutNameLen := length(AccountName);
       for i:=Low(CMD_AUTH_LOGON_CHALLENGE.AccountName) to High(CMD_AUTH_LOGON_CHALLENGE.AccountName) do begin
          CMD_AUTH_LOGON_CHALLENGE.AccountName[i] := byte(Upcase(AccountName[i+1]));
       end;
       Form1.IdTCPClient1.WriteBuffer(CMD_AUTH_LOGON_CHALLENGE, PacketSize, true);
       lst.Free;
    End;
    Voilà Donc quand j'envoi mon paquet ( a l'heure actuelle j'utilise netcat avec les paramètre nc.exe -l -p 3724 -o dump.txt pour avoir un serveur et identifier correctement les paquets ) le record est parfaitement compléter dans le programme ( vérifié avec le debuggueur ) mais le paquet recu est bien jusqu'au champ AccountName , j'ai l'impression que ce qu'il envoit c'est la valeur du pointeur mais j'en suis absolument pas sure .

    Merci beacoups de vos réponses.

    P.S : Les sources ne sont pas toutes ici les variable qui ne sont pas déclarer ici sont déclarer plus loin ^^, AccountName est un string.

  2. #2
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 13
    Points : 7
    Points
    7
    Par défaut
    A l'heure actuelle je suppose que le bug vient de indy ... il ne prend pas la valeur des informations qui sont dans le tableau dynamique ... je suppose .... , si quelqu'un est connaisseur de l'aide ne serait pas de refus

    ++

  3. #3
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 449
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 449
    Points : 5 876
    Points
    5 876
    Par défaut
    salut

    la premiere chose a faire serai d'essayer la meme methode avec un array non dynamique ou un shortstring et voir le resultat

    mais a priorie tu devrais etre dans le vrai vu que le tableau dymaique est une sorte de pointeur
    tu devrais avoir le meme probleme avec des objet

    mais plutot que de passer par un record pourquoi ne pas mettre tes donnée dans un stream ?

    @+ Phil

  4. #4
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 13
    Points : 7
    Points
    7
    Par défaut
    Merci beacoup de ta réponse

    * J'ai essayé de faire avec un tableau a longueur constante ce qui explique mes affirmation ou suggestions sur les raisons du bug

    * Pour le Stream ben enfaite je savais pas que ca existait ( je suis tout nouveau en delphi mais j'ai des bonnes bases en Pascal ) Si tu pouvais m'éclairer.

    ++

  5. #5
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 449
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 449
    Points : 5 876
    Points
    5 876
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    ....
    var
      myStream:TMemoryStream;
      Datas      : T_CMD_AUTH_LOGON_CHALLENGE
    begin
      myStream:=TMemoryStream.Create;
      try
        TransFormMesdataenStream(myStream,Datas)
        idTCPClient1.WriteInteger(memStream.size);
        idTCPClient1.WriteBuffer(myStream.Memory^, myStream.Size, True);
      finally
        myStream.Free;
      end;
    end;
    @+ Phil

  6. #6
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 13
    Points : 7
    Points
    7
    Par défaut
    Merci beacoup de ton aide je pense refaire une partie de mon programme en utilise les stream

  7. #7
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 886
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 886
    Points : 11 410
    Points
    11 410
    Billets dans le blog
    6
    Par défaut
    +1 pour les streams !

    mais si tu transformes AccountName en ShortString (jusqu'à 255 caractères) ou en String[30], pe
    => ce ne sera plus un pointeur, mais ta chaîne, dans la structure

  8. #8
    Membre à l'essai
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2005
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2005
    Messages : 15
    Points : 12
    Points
    12
    Par défaut
    Bonjour,
    il est tout à fait normal que seul le pointeur soit envoyé avec une fonction "writeBuffer", et pas le contenu de la chaîne.
    Lorsque que vous faites
    SetLength(CMD_AUTH_LOGON_CHALLENGE.AccountName, length(AccountName));
    cela a pour effet de réserver l'espace mémoire nécessaire pour la chaîne, et d'indiquer son adresse dans le champ AccountName. Mais en aucun cas la réservation n'est faite de manière contigüe à votre record, puisque les tableaux dynamiques sont des pointeurs...
    Or la fonction writeBuffer écrit une "suite contigüe d'octets", sans interpréter les pointeurs, puisqu'elle ne dispose d'aucune information de type sur le contenu.
    Une solution serait de réserver en une seule fois la taille complete du record chaîne incluse, en utilisant getMem :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    type P_CMD_AUTH_LOGON_CHALLENGE = ^T_CMD_AUTH_LOGON_CHALLENGE;
    var p:P_CMD_AUTH_LOGON_CHALLENGE;
    begin
       getMem(p,PacketSize);
       p.Opcode := 0;
       [...]
       p.AccoutNameLen := length(AccountName);
       CopyMemory(@(p.accountName),@(accountName[1]),lengt(AccountName)); //en supposant que accountName est du type string
     
       //writeBuffer 
     
       freeMem(p,PacketSize);
    end;
    Cependant je ne connais pas le type des paramètres dans le cas TIdTCPConnexion.writeBuffer, donc je ne sais pas s'il acceptera en entrée le pointeur p, car l'aide de Delphi semble mentionner un descendant de TMemoryStream (dans ce cas je ne comprends pas comment cela pouvait marcher avec une simple structure dans votre exemple).

    Dans tous les cas la solution avec les streams répond très bien au problème et elle est plus propre et plus portable.

Discussions similaires

  1. Problème avec un tableau HTML dans un While
    Par Manutchelo dans le forum Langage
    Réponses: 6
    Dernier message: 22/08/2011, 23h46
  2. [JpGraph] Erreur avec le tableau dans une fonction
    Par gtraxx dans le forum Bibliothèques et frameworks
    Réponses: 4
    Dernier message: 12/01/2009, 22h01
  3. Problème de libération de tableau dynamique
    Par Rustine dans le forum Delphi
    Réponses: 5
    Dernier message: 18/09/2006, 15h58
  4. Problème de libération de tableau dynamique
    Par cali1983 dans le forum C++
    Réponses: 4
    Dernier message: 14/03/2006, 09h30
  5. Delphi: Lecture d'un fichier avec un tableau dynamique
    Par grégoire2 dans le forum Langage
    Réponses: 8
    Dernier message: 10/02/2006, 19h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo