Violation d'acces en delphi [Résolu]

Messages postés
10
Date d'inscription
lundi 25 mai 2009
Dernière intervention
21 septembre 2009
- 6 sept. 2009 à 13:15 - Dernière réponse :
Messages postés
3869
Date d'inscription
samedi 22 décembre 2007
Derniè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
Afficher la suite 

Votre réponse

16 réponses

Meilleure réponse
Messages postés
3982
Date d'inscription
mardi 8 mars 2005
Dernière intervention
7 novembre 2014
- 6 sept. 2009 à 13:25
3
Merci
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.

Merci cs_rt15 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 88 internautes ce mois-ci

Commenter la réponse de cs_rt15
Messages postés
4304
Date d'inscription
samedi 16 octobre 2004
Dernière intervention
9 mars 2018
- 6 sept. 2009 à 16:04
0
Merci
et n'oublie pas de nous soumettre le code de declaration des matrices et la fonction recursive.
Commenter la réponse de f0xi
Messages postés
10
Date d'inscription
lundi 25 mai 2009
Dernière intervention
21 septembre 2009
- 7 sept. 2009 à 15:15
0
Merci
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?

rt15, je vais essayer de suivre ton conseil.
Commenter la réponse de anyaa
Messages postés
10
Date d'inscription
lundi 25 mai 2009
Dernière intervention
21 septembre 2009
- 8 sept. 2009 à 14:57
0
Merci
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??
Commenter la réponse de anyaa
Messages postés
3982
Date d'inscription
mardi 8 mars 2005
Dernière intervention
7 novembre 2014
- 8 sept. 2009 à 15:27
0
Merci
Grise ?
La violation d'accès est dans l'assembleur ?
Si tu montes ou descends dans cette fenêtre, tu ne tombes pas sur un nom de fonction ?
Commenter la réponse de cs_rt15
Messages postés
10
Date d'inscription
lundi 25 mai 2009
Dernière intervention
21 septembre 2009
- 14 sept. 2009 à 14:16
0
Merci
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.
Commenter la réponse de anyaa
Messages postés
3982
Date d'inscription
mardi 8 mars 2005
Dernière intervention
7 novembre 2014
- 14 sept. 2009 à 14:51
0
Merci
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é.
Commenter la réponse de cs_rt15
Messages postés
3869
Date d'inscription
samedi 22 décembre 2007
Dernière intervention
3 juin 2016
- 14 sept. 2009 à 15:12
0
Merci
Ca n'aide pas beaucoup non plus de savoir que ton programme a planté dans une API ... mieux vaut utiliser GetLastError

Cordialement, Bacterius !
Commenter la réponse de Bacterius
Messages postés
3982
Date d'inscription
mardi 8 mars 2005
Dernière intervention
7 novembre 2014
- 14 sept. 2009 à 16:27
0
Merci
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.
Commenter la réponse de cs_rt15
Messages postés
3982
Date d'inscription
mardi 8 mars 2005
Dernière intervention
7 novembre 2014
- 14 sept. 2009 à 17:03
0
Merci
Voilà une petite démo :

procedure TForm1.Button1Click(Sender: TObject);
begin
  SetLastError(39);        // 39 = disque plein
  try
    MessageBox(0, PChar(1), 'Hello world !', MB_OK);
  except
    RaiseLastOSError;
  end;
end;


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.
Commenter la réponse de cs_rt15
Messages postés
10
Date d'inscription
lundi 25 mai 2009
Dernière intervention
21 septembre 2009
- 14 sept. 2009 à 17:37
0
Merci
slt,
merci pr vos propositions. je vois que je m'etais trompee, en fait ce qui etait en gras c'est ca: @LStrAsg.
Commenter la réponse de anyaa
Messages postés
3982
Date d'inscription
mardi 8 mars 2005
Dernière intervention
7 novembre 2014
- 14 sept. 2009 à 18:28
0
Merci
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...

Bonne recherche !
Commenter la réponse de cs_rt15
Messages postés
3982
Date d'inscription
mardi 8 mars 2005
Dernière intervention
7 novembre 2014
- 14 sept. 2009 à 18:35
0
Merci
Houps, pardon, pas la bonne impression écran.

Voilà la bonne :


Pour LStrAsg, je l'ai simplement googelisé pour tomber sur ça et et la page suivante.
Commenter la réponse de cs_rt15
Messages postés
10
Date d'inscription
lundi 25 mai 2009
Dernière intervention
21 septembre 2009
- 16 sept. 2009 à 13:53
0
Merci
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.
Commenter la réponse de anyaa
Messages postés
10
Date d'inscription
lundi 25 mai 2009
Dernière intervention
21 septembre 2009
- 21 sept. 2009 à 19:53
0
Merci
Bonsoir,
j'ai fini par trouver l'erreur. ça concernait la taille d'une matrice qui était trop petite.
Commenter la réponse de anyaa
Messages postés
3869
Date d'inscription
samedi 22 décembre 2007
Dernière intervention
3 juin 2016
- 22 sept. 2009 à 06:41
0
Merci
On va enfin pouvoir fermer ce thread

Cordialement, Bacterius !
Commenter la réponse de Bacterius

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.