anyaa
Messages postés10Date d'inscriptionlundi 25 mai 2009StatutMembreDernière intervention21 septembre 2009
-
6 sept. 2009 à 13:15
Bacterius
Messages postés3792Date d'inscriptionsamedi 22 décembre 2007StatutMembreDernière intervention 3 juin 2016
-
22 sept. 2009 à 06:41
Anyaa Bonjour a tous,
je m'excuse d'avancs pour les acccents car je travaille sur un clavier 'qwerty'.
J'ai realise un programme en delphi 7, il s'agit d'une procedue recursive sur une matrice (carree symetrique).
ce programme marche sur certaines matrices et pas sur d'autre. je l'ai excecute sur trois matrices de taille 6, mais sur l'une des trois, le programme rencontre l'erreur suivante:
Le projet aff.exe a provoqué une classe d'exception EAccessViolation avec le message 'Violation d'accès à l'adresse 00403F16 dans le module 'aff.exe'. Lecture de l'adresse 00071AC6'.
je ne suis pas experte en programmation et je ne sais vrai;ent pas quoi faire.
salutations
A voir également:
Violation d'accès à l'adresse
Violation d'accès à l'adresse dans le module - Meilleures réponses
cs_rt15
Messages postés3874Date d'inscriptionmardi 8 mars 2005StatutModérateurDernière intervention 7 novembre 201413 6 sept. 2009 à 13:25
Salut,
L'instruction processeur située à l'adresse 00403F16 essaie de lire l'adresse 00071AC6. Cependant 0071AC6 n'est pas une adresse valide pour le processus. Cela peut se produire si tu dé-référence un pointeur qui pointait sur n'importe quoi, si tu vas trop loin dans un tableau...
Il faut que tu commences par localiser la ligne de code source posant problème.
Exécute ton programme dans l'IDE pour trouver la ligne de code correspondante.
Tu peux aussi utiliser "Chercher"->"Erreur à l'exécution..." (Utilisable quand ton programme tourne) et mettre l'adresse 00403F16. Cela te mène directement à la ligne de source correspondant à l'instruction.
Une fois que tu as la ligne tu peux essayer de comprendre quel morceau de ligne pose problème.
anyaa
Messages postés10Date d'inscriptionlundi 25 mai 2009StatutMembreDernière intervention21 septembre 2009 7 sept. 2009 à 15:15
bonjour,
merci pr vos suggestions.
En fait, je construis un arbre n-aire et je ne peux supprimer les pointeur qu'a la fin du programme car sinon je perds toutes les adresses des noeuds.
est ce que ca pourrait ^etre du a ca?
anyaa
Messages postés10Date d'inscriptionlundi 25 mai 2009StatutMembreDernière intervention21 septembre 2009 8 sept. 2009 à 14:57
Bonjour,
r15, j'ai suivi ton conseil mais ca ne m'a pas aide car je n'ai pas su interpreter la ligne selectionnee sur la fenetre en gris. de plus, le meme message apparait quand je fais des traitement sur les tables de ma base de donnees.
que pourrais-je faire??
Vous n’avez pas trouvé la réponse que vous recherchez ?
anyaa
Messages postés10Date d'inscriptionlundi 25 mai 2009StatutMembreDernière intervention21 septembre 2009 14 sept. 2009 à 14:16
Bonjour r15,
effectivement,quand je cherche l'erreur une fenetre grise s'affiche et non pas l'editeur de code.
j'ai essayer cette methode sur un autre programme et dans ce cas, une ligne sur l'editeur de code etait en bleu et j'ai trouve mon erreur.
pour ce qui est de de mon programme principal, sur la fenetre grise en montant quelques lignes il y a inscrit en gras:"mov exc, [edx_$08]".
saurais tu ce que ca signifie?
merci encore.
cs_rt15
Messages postés3874Date d'inscriptionmardi 8 mars 2005StatutModérateurDernière intervention 7 novembre 201413 14 sept. 2009 à 14:51
mov exc, [edx_$08]
Tel quel ça ne veut strictement rien dire car le "_" est très probablement un "-".
Mais bon quoiqu'il arrive, c'est très insuffisant pour comprendre. C'est une bête instruction processeur comme il y en a des kilomètres dans ton programme...
Non, ce qui pourrait éventuellement aider, c'est un symbole. Comme tu es en 00403F16, tu es très certainement dans du code compilé par Borland ou CodeGear, donc tu devrais en avoir un peu. Il faudrait que tu utilises l'ascenseur pour monter et trouver le premier symbole. Souvent, il s'agit du nom de la fonction dans laquelle le programme a planté.
cs_rt15
Messages postés3874Date d'inscriptionmardi 8 mars 2005StatutModérateurDernière intervention 7 novembre 201413 14 sept. 2009 à 16:27
Gné ?
Par où commencer ?
C'est vrai que trouver le nom de la fonction peut ne pas l'aider. Mais si c'est par exemple Move ou autre (C'est un programme de manipulation de matrices...), ça peut être intéressant.
Mais s'il y a une chose au monde qui ne peut pas l'aider, c'est GetLastError, et ce pour différentes raisons.
1) GetLastError est une fonction de windows, alors que l'erreur à lieu dans les bibliothèques fournies avec Delphi. En effet, l'adresse de base de l'image par défaut sous Delphi est 00400000 (Visible dans les options du lieur). C'est l'adresse à laquelle est chargée le .exe. Les dlls de l'API Win32 sont quand à elle souvent chargées en 7XXXXXXX. L'erreur de anyaa a lieu à l'adresse 00403F16, donc dans le .exe (Qui plus est c'est confirmé par le "dans le module 'aff.exe'"). Et il y a peu de chance qu'une erreur de l'OS provoque une erreur dans les libs Borland, qui doit tester les codes retour et déclencher une exception explicite en cas de problème.
2) Une violation d'accès déclenche une interruption non maskable. C'est une erreur très grave (C'est souvent à elle qu'on doit les écrans bleus, quand elle à lieu dans du code en ring 0). Le code de l'interruption ne s'amuse pas à analyser le problème en détail. Il donne l'adresse de l'instruction fautive, si c'est pour de l'écriture ou de la lecture, et l'adresse invalide. Il ne va pas commencer à faire des SetLastError. Par contre il va déclencher une exception "access violation".
3) Ce point découle du 2). Que ce passe t'il quand une violation d'accès à lieu dans une API Win32 ? L'API Win32 n'est pas du tout blindé par rapport au violation d'accès, car il est tout simplement impossible d'y être blindé (Il y avait bien IsBadReadPtr/IsBadWritePtr mais elles n'ont pas été utilisées et sont obsolètes). Et donc si on lui passe des arguments avec des adresses incorrectes, l'API Win32 fait comme la lib Borland, elle fait un beau plantage, et ne va surtout pas chercher à comprendre pourquoi ou essayer de traiter l'exception.
On fait un SetLastError avant l'appel à la fonction Win32, indiquant que la dernière erreur est disque plein. Puis on passe l'adresse 1 comme adresse du message à mettre dans la MessageBox, adresse invalide et différente de nil.
RaiseLastOSError génère une exception avec un message d'erreur basé sur GetLastError.
Quand on exécute ce code dans le débogueur, on voit deux exception :
Le projet Project1.exe a provoqué une classe d'exception EAccessViolation avec le message 'Violation d'accès à l'adresse 7E3A15F7 dans le module 'user32.dll'. Lecture de l'adresse 00000001'. Processus stoppé. Utilisez Pas-à-pas ou Exécuter pour continuer.
On retrouve bien user32 qui contient MessageBoxA, l'adresse en 7XXXXXXX, la lecture, et l'adresse posant problème : 1.
Puis l'exception est traitée et RaiseLastOSError fait son boulot. Il fait un GetLastError et génère une exception correspondante :
Le projet Project1.exe a provoqué une classe d'exception EOSError avec le message 'Erreur système. Code : 39.
Le disque est plein'. Processus stoppé. Utilisez Pas-à-pas ou Exécuter pour continuer.
Mais quand il fait son GetLastError, il récupère la valeur que l'on a settée avant l'appel à MessageBox. MessageBox n'a pas mis à jour la dernière erreur avec un nouveau code.
De même, ce code ne sert à rien, du moins en ce qui concerne les violation d'accès :
nResult:= MessageBox(0, PChar(1), 'Hello world !', MB_OK);
if nResult = 0 then
begin
// Il y a eu une erreur dans MessageBox
end;
Les arguments passés doivent être correctes d'un point de vue mémoire, un point c'est tout.
cs_rt15
Messages postés3874Date d'inscriptionmardi 8 mars 2005StatutModérateurDernière intervention 7 novembre 201413 14 sept. 2009 à 18:28
Hé bin voilà.
LStrAsg recopie une chaîne dans une variable globale.
Donc on peut reproduire ton problème "facilement" comme ça :
unit Unit1;
...
var
a: String;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
b: String;
begin
asm
mov b, 1
end;
a:= b;
end;
end.
Et on tombe là dessus :
mov ecx, [edx-$08]
Ca te rappelle rien ?
C'est b qui est passé dans edx, une chaîne étant un pointeur. Il y a une vérification edx différent de nil, puis on va taper en adresse pointée par edx - 8. Qu'est ce qu'il y a en -8 ? Le compteur de référence de la chaîne.
Vu que j'ai mis b à 1, l'adresse posant problème est 1 - 8 = FFFFFFF9.
Donc dans ton cas, la chaîne fautive pointe sur 00071AC6 + 8 = 00071ACE.
Maintenant tu as une idée beaucoup plus précise de ce que tu recherches, non ?
Comment ça non ?
Ton problème est vraisemblablement l'affectation d'une chaîne invalide à une variable globale. En ce qui concerne la variable globale, il peut s'agir aussi d'un tableau de string, d'un membre d'une instance de classe ou de structure globale... Il se peut aussi que cette affectation de chaîne ne se fasse pas explicitement dans ton code (Appel d'une méthode Delphi qui fasse l'affectation).
Tu dois afficher les résultats de tes calculs, non ? Tu dois y convertir des nombres en chaînes, non ? Le problème peut être par là.
Après faut aussi se demander pourquoi la chaîne à affecter est invalide. Il peut s'agir d'un écrasement mémoire dût au calcul, d'une non initialisation...
anyaa
Messages postés10Date d'inscriptionlundi 25 mai 2009StatutMembreDernière intervention21 septembre 2009 16 sept. 2009 à 13:53
salut,
merci pour toutes les explications et les details que tu m'as donnes, je vais m'y plonger pour voir ou se situe mon probleme.
encore une fois, merci pr tout.
bonne continuation
ps:je ne suis pas une habituee des forums et ton aide m'a touchee.