Erreur sur FindComponent

Messages postés
1649
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
25 juillet 2014
- - Dernière réponse : jlen100
Messages postés
1649
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
25 juillet 2014
- 7 avril 2006 à 15:41
Salut,

une fois n'est pas coutume aujourd'hui c'est moi qui vais poser une colle.

Dans le code suivant:

with TStaticText(findcomponent('CM'+inttostr(axe)))do

begin

Tag:=tag+step;

caption:= inttostr(tag);

end;

si je déclare axe en shortint j'ai une erreur d'exécution
(violation d'accès) alors que tout se passe normalement si
jedéclare axe en integer

c'est la solution que j'ai choisi mais je ne voudrais pas mourir
idiot alors si quelqu'un à une explication : je pense qu'elle tient à
la différence de type (1 octet contre 4 ) mais ce n'est pas très
cohérent.



@+

jlen
Afficher la suite 

11 réponses

Messages postés
2349
Date d'inscription
dimanche 5 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2010
12
0
Merci
"F1ndComponent" ? ton "i" est si proche du "1" sur ton clavier ? ^^
j'ai donc modifié le titre.
Commenter la réponse de JulioDelphi
Messages postés
1649
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
25 juillet 2014
7
0
Merci
excuse moi JulioDelphi mais en fait cela devait être un 'I' majuscule (le doigt qui est resté trop longtemps sur le MAJ ou la vue un peu basse???) mais c'est vrai qu'avec un 'i' minuscule c'est plus lisible. sinon cela fait un FindComponent de compétition!! quoiqu'il ait des ratés à l'allumage



@+

jlen
Commenter la réponse de jlen100
Messages postés
329
Date d'inscription
lundi 30 décembre 2002
Statut
Membre
Dernière intervention
10 mars 2012
0
Merci
non le Shortint et Integer n'est pas la cause du crash !!!

déja là !! il ya une maladresse d'utilisation de FindComponent car en effet FindComponent renvoi nil dans le cas ou le composant n'a pas été trouvé donc déja le code s'écrit comme ça :

var
st : TStaticText;
begin
St := FindComponent(Format('CM%u' , [axe]));
if St <> nil then
begin
with St do
begin
Tag := Tag + Step;
Caption:= inttostr(tag);
end;
end;
end;
ici ça ne plantera pas car si le composant n'existe pas on ne fait rien !!!
donc ton problème est que si jamais Axe contient un chiffre qui ne fait pas parti de CM+AXE alors ça plante !!!, donc il faut être sûr que Axe est correctement initialisé !!!
Commenter la réponse de cs_shining
Messages postés
329
Date d'inscription
lundi 30 décembre 2002
Statut
Membre
Dernière intervention
10 mars 2012
0
Merci
arf j'ai cliquer trop vite !!!
biensur il faudra surtypé FindComponent car il renvoi un TComponent où nil dans le cas contraire !!!

meaculpa.
Commenter la réponse de cs_shining
Messages postés
1649
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
25 juillet 2014
7
0
Merci
je vois ce que tu veux dire mais dans le 2 cas le composant
existe (créé à la construction) et en fait en appliquant ce que tu
donnes il ne plantera pas mais il faira comme s'il n'avait pas
trouvé le composant et ce n'est pas le but recherché

En fait tu as trouvé l'erreur :

elle est dans :

'CM'+inttostr(axe) qui apparement à du mal avec le shortint si la fonction est appelée comme argument alors que Format('CM%u' , [axe]) fait correcement la conversion

Le probléme est donc déplacé mais toujours pas expliqué!!

pourquoi'CM'+inttostr(axe) ne renvoie la bonne valeur s'il est utilisé comme argument et quand axe est un shortint???

@+

jlen
Commenter la réponse de jlen100
Messages postés
329
Date d'inscription
lundi 30 décembre 2002
Statut
Membre
Dernière intervention
10 mars 2012
0
Merci
je viens de faire le teste et ça ne change rien chez moi que sa soit Axe en Integer où ShortInt !!!, donc c'est bien ce que je disais !!! ShortInt n'est pas vraiment la cause, quoique .. un ShortInt est compris entre -127 et 127 on ne peut donc le depasser, mais dans ce cas Delphi nous aura prevenu avec un beau "L'expression constante dépasse les limites de sous-étendue"
maintenant tout le problème semble venir du piège due à la création de composant en runtime !!!, en effet lorsqu'on mets sur la fiche un composant depuis la palette, l'inspecteur d'objet initialise le Nom du composant en fonction de ceux déja disponible sur la fiche exemple Label1, Label2 ect..
maintenant lorsqu'on créé nous même un composant son nom n'est pas initialisé
d'où le problème

car si je prends ton exemple

CM1 := TStaticText.Create(Self);

Attention au piège le composant possède le Nom CM1 en tant que variable mais son nom n'est pas celui de CM1 !!!!
il faudra mettre

with CM1 do
begin
Name := Format(CM%u', [Index]);
end;
voilà pourquoi le composant CM1 existe mais si l'on tente de recupérer ce compo depuis FindComponent(..) la fonction FindComponent renvoie nil
pour s'en convaincre il suffit de faire CM1 := TStaticText.Create(Self);
Caption := CM1.Name

moi je pense que le problème viens de là !!!
sinon montre ton bout de code afin de voir où se situe le problème !!
Commenter la réponse de cs_shining
Messages postés
1649
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
25 juillet 2014
7
0
Merci
Cela marche avec format() mais pas avec inttostr();

le composant n'est pas créer dynamiquement mais à la conception (posé
sur la fiche à partir de la palette); donc les composants CM1 CM2 CM3
CM4 existent le problème ne vient donc pas d'ici

en fait ici on ne fait qu'afficher la prochaine position du moteur et on la range dans le tag



procedure TEDITRAJ.Timer4Timer(Sender: TObject);

var buf:string;

axe integer;//ou shortint



begin

axe:= Timer4.tag;//on récurpère le N° d'axe à piloter

//Process.MOVEF( NumCarte.Value,axe,Step); //la version qui plante

//la vesrion qui fonctionne ou je n'ai repris que l'envoi de la commande sans attendre la réponse du microcontroleur ~4ms

buf: =#170+chr((axe-1))+process.converttoint(Step);//on prépare la commande

buf:= chr(length(buf))+buf;

Card[NumCarte.Value].port.ClearBuffer(true,true);

Card[NumCarte.Value].port.WriteStr(buf); //on envoie la commande

with TStaticText(findcomponent('CM'+inttostr(axe))) do

begin

//ici on mets à jour le compteur et l'affichage

Tag: =tag+step;

caption:= inttostr(tag);

end;

end;

timer4.Tag est intialisé entre 1 et 4 et timer4.Interval entre 20 et 100; et ceci que l'on soit en integer ou en shortint

Si axe n'était pas dans cet interval j'aurais une erreur d'exécution au
niveau du microcontroleur ce qui n'est pas le cas d'autre part les
initialisations sont identiques que j'utilise un integer ou un shortint

en fait j'ai trouvé une partie de l'explication:

dans la version qui pose probléme je passe par un évènement dont
j'attends le déclenchement or la gestion par window impose un délai
d'environ 16ms ce qui dans le pire des cas, bien que la la réponse
revienne bien avant(~2ms) la fin du délai du timer on risque
de faire redéclencher une interruption du timer pendant la
recherche du composant ;donc l'erreur (violation d'accès) n'est peut
être pas du au findcomponent mais au timer!!!

C'est quand j'ai mesuré les délais de réponse de windows que j'ai
modifié la gestion , ce n'est pas très logique de renvoyer une commande
sans attendre la fin d'exécution de la précédente mais tant que MS nous
pondras des gestions d'évènement aussi M...e je n'aurais pas le choix
(même en modifiant la priorité du thread cela ne change pas grand chose
en final)



@+

jlen
Commenter la réponse de jlen100
Messages postés
329
Date d'inscription
lundi 30 décembre 2002
Statut
Membre
Dernière intervention
10 mars 2012
0
Merci
Ouep ton exemple marche correctement néanmoins au sujet du Timer(je crois aussi que ça vient de là)
1) soit le timer est créé dynamiquement et là il se peut que le Timer déclenche l'évènement OnTimer avant même de l'initalisé, dans ce cas mettre Timer4.Enabled = False
Timer4.Tag := ??
Timer4.Enable := True

Soit plus grave encore le Timer4 tourne en continue ... et là n'ya t'il pas un risque que le timer déclenche aussi l'évènement OnTimer avant même l'initalisation du Tag ?, mystère !!!

Toujours est-il que tu peux mettre un
// MaxValue étant un chiffre à ne pas dépasser
// MinValue valeur minimale ...
if Tag in [MinValue..MaxValue] then else MessageBox('Error Tag=' + IntToStr(Tag));

@+
Commenter la réponse de cs_shining
Messages postés
1649
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
25 juillet 2014
7
0
Merci
le timer est créé à la conception avec enabled:=false;et tag:=1( par
sécurité); il n'est mis a true qu'a l'initialisation de la tache.

en gros le timer est dechenché par 8 boutons corespondant à 4 axes on
récupère le tag du bouton est en focntion de ce tag on positionne le
tag du timer ce n'est qu'après que que je mets l'enabled à true
et donc le tag est toujours compris entre 1et 4 d'autre part si le
lance le timer avnt initialisation j'aurais une erreur dans
l'instruction MOVEF avec port non ouvert. idem pour l'instruction:
Card[NumCarte.Value].port.ClearBuffer(true,true); qui provoque
une erreur si le port n'est pas ouvert ou n'existe pas. je serais donc
viré du prog avant d'atteindre le findcomponent.



Mais la gestion des évenements par windows est plutot cahotique.

les tests d'hier ont révélé des choses encore plus étranges:

suivant que je compile sous D7 ou D2005 je n'ai pas le même résultat.
Pire sous D2005 j'ai un résultat quand je l'excute sous débogger et un
autre quand je lance l'appli seule et cela se complique car si j'ouvre
D2005 seul (sans charger le projet) j'ai le résultat initial.... à se
les prendre et à se les mordre!!!!

et les écarts ne sont pas minimes les différences de timing vont de 1 à
10 et ce qui est le plus surprenant c'est qu'ils sont les plus courts
quand DELPHI est ouvert alors que l'espace mémoire est plus faible et
que le nombre de processus et de threads est plus important.

resultat je suis repassé sous D7 pour terminer ces tests. Comme si mes Co...ries ne suffisaient pas !!

@+

jlen
Commenter la réponse de jlen100
Messages postés
329
Date d'inscription
lundi 30 décembre 2002
Statut
Membre
Dernière intervention
10 mars 2012
0
Merci
donc si je comprends bien avec ton D2005 même en faisant "nouveau projet" + "exécuter" ça plante ?

dans ce cas là c'est probablement le JIT qui en est la cause !!!
JIT = Just in time deboggeur <== c'est un ActiveX et c'est rare mais ça arrive que le JIT déconne il ya quelques ClassID inscrite dans la BDR parfois la cause provient du fait qu'on installe D2005 et une version anterieur !! Delphi n'aime pas trop la cohabitation de diverses versions de Delphi/CBuilder car certaines BPL sont en commun même si Borland rajoute le numéro de version afin d'évité tout conflit

dans le cas contraire il faudra mettre des break points dans des endroits tratégique de ton appli par exemple juste au début de la procedure OnTimer puis après "buf:=#170+chr((axe-1))+process.converttoint(Step);//on prépare la commande" et après " Card[NumCarte.Value].port.WriteStr(buf);//on envoie la commande"
Comport aussi utilise des Pointeurs, le fait peut être que les délais sont très court peuvent avoir un impacte sur les pointeurs, c'est généralement le cas quand on a une exception "00000000" <== pointeur
Commenter la réponse de cs_shining
Messages postés
1649
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
25 juillet 2014
7
0
Merci
C'est pire que cela: si je lance l'aplli seule à partirde l'exe j'ai un
timing 16ms/boucle normal puisque j'ai la gestion de windows. Mais si
j'ouvre D2005 (sans rien faire d'autre avec juste la page d'accueil)le
timing descend à 1/1,6ms /boucle. C'est à dire ce que j'obtiens la même
chose qu'en lançant l'appli par exécuter de D2005 surprenant non? je me
suis dit à départ que c'était le débogger qui interceptait les messages
Windows et qui les traitait à sa sauce mais celà ne tient pas vec une
appli indépendante ou alors il fauda qu'il donne leur recette à
MicroSoft parcequ'un facteur de performance de 1 à 10 c'est pas mal!!

Pour le plantage effectivement j'ai plusieurs versions qui cohabitent
sur ce PC . mais comme D2005 est une version perso qui ne me sert
normalement qu'à tester la compitibilté entre version je ne tiens pas à
désinstaller les versions pros. Je l'ai utilisée parce que c'est vrai
que l'IDE est plus agréable et comme les autres PC du réseau sont des
portables et que je n'aime pas trop ces bestioles pour bosser en
permanence dessus il faudra que je fasse avec.

Merci quand même pour les tuyaux même si celà n'a pas résolu le fond du problème



@+

jlen
Commenter la réponse de jlen100