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

C++Builder Discussion :

Violation d'accès destruction TForm


Sujet :

C++Builder

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé

    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    1 163
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 163
    Par défaut Violation d'accès destruction TForm
    Bonjour à tous,

    j'ai un petit problème qui remonte à la surface. Ce "bug" avait mystérieusement disparu pour revenir maintenant...
    Voilà mon problème :

    j'ai un programme qui fonctionne très bien. Plus d'avertissements à la compilation (à part les Argument Sender pas utilisé) et Codeguard ne se manifeste plus pendant toute l'éxecution. Ce programme utilise aussi un paquet de composant fait maison. Idem ceux-ci ne donnent plus d'avertissement et une éxecution avec Codeguard activé ne donne rien non plus.

    Je lance mon programme : impecable. Je le ferme, tout le code qui se trouve dans le FormDestroy de ma fenêtre principale se passe sans problème. De même la destruction de la seule autre fiche crée automatiquement par builder n'éxecute aucune code particulier.

    Arrivé à la fin du FormDestroy de ma fiche principale (exactement sur le } en mode pas à pas) j'obtiens cela :

    Citation Envoyé par Message d'erreur
    Le projet Mon_Projet.exe a provoqué une classe d'exception EInvalidPointer avec le message 'Opération de pointeur incorrecte'. Processus stoppé. Utilisez Pas-à-pas ou Exécuter pour continuer.
    Si je continue l'execution le message suivant apparaît :

    Citation Envoyé par Message d'erreur 2
    Le projet Mon_Projet.exe a provoqué une classe d'exception EExternalException avec le message 'Exception externe C0000025'. Procesuss stoppé.....
    Parfois builder indique aussi que l'erreur surivent de lors de l'éxecution de la ligne suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    /* TCustomForm.Destroy */ inline __fastcall virtual ~TForm(void) { }
    du fichier Forms.hpp


    Voila je suis un peu à cour d'idée pour trouver d'où cela vient, donc si vous avez une petite idée merci de m'aider !

  2. #2
    Rédacteur
    Avatar de Greybird
    Inscrit en
    Juin 2002
    Messages
    673
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 673
    Par défaut
    Utilises-tu de la création dynamique de composants ?

    Si oui, ne supprimes-tu que les composants créés dynamiquement avec un Owner NULL ?

  3. #3
    Membre éprouvé

    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    1 163
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 163
    Par défaut
    Après vérification : non je ne crée pas de composants dynamiquement.
    Merci quand même !

  4. #4
    Rédacteur
    Avatar de Greybird
    Inscrit en
    Juin 2002
    Messages
    673
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 673
    Par défaut
    Tu devrais essayer d'obtenir une trace complète de l'exception.

    Pour cela, il existe un certain nombre d'outils.

    Tu en trouveras une liste ici :
    http://www.blong.com/Contents.htm, à Delphi & C++Builder Links | Delphi Components/Tools | Error Trapping

  5. #5
    Membre Expert
    Avatar de Gilles Louïse
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    421
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2002
    Messages : 421
    Par défaut
    L'expérience montre qu'il faut faire attention à l'événement OnDestroy au sens où les composants dépendant de la fenêtre risquent de ne plus être accessibles car ils ont été détruits juste avant. Pour éviter ces problèmes, on préfère utiliser l'événement OnClose, tout est alors encore disponible.

    À bientôt
    Gilles

  6. #6
    Membre confirmé

    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    137
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 137
    Par défaut
    Pour éviter ces problèmes, on préfère utiliser l'événement OnClose, tout est alors encore disponible.
    On peut aussi utiliser le destructeur.

  7. #7
    Membre éprouvé

    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    1 163
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 163
    Par défaut
    Merci Gilles Louïse pour ton information. J'ai changé mon code pour le mettre dans l'évènement OnClose mais sans succès. Cela n'a rien changé.

    Je vais tenter d'obtenir une trace complète de l'exception !

    Merci !

    ----------------------------------------------------------------------------
    EDIT
    Je viens de télécharger Eurekalog et j'ai lancé mon programme en l'utilisant. Eurekalog ne réagit pas lorsque l'excpetion est déclenché (pourtant Eurekalog est bien activé). J'ai toujours la même erreur lorsque je quitte mon programme à l'exception des adresses mémoire qui changent un peu...

  8. #8
    Membre éprouvé

    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    1 163
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 163
    Par défaut
    Bon j'ai finallement réussi à utiliser EurekaLog : il fallait que je désactive CodeGuard et que je ne lance pas l'application depuis l'IDE.

    Voici ce que m'indique le Eurekalog :

    Citation Envoyé par EurekaLog - Onglet General
    Exception:
    ------------------------------------------------
    2.1 Date : Tue, 2 Aug 2005 11:02:43 +0200
    2.2 Address: 40002FF7
    2.3 Module : rtl60.bpl
    2.4 Type : EInvalidPointer
    2.5 Message: Opération de pointeur incorrecte.

    Active Controls:
    ---------------------------------
    3.1 Form Class : TApplication
    3.2 Form Text : MonApplication
    3.3 Control Class: TApplication
    3.4 Control Text : MonApplication
    Citation Envoyé par EurekaLog - Premières lignes du stack
    Call Stack Information:
    ---------------------------------------------------------------------------------------
    |Address |Module |Unit |Class |Procedure/Method |Line|
    ---------------------------------------------------------------------------------------
    | Running Thread: ID=4064; Priority=0; Class=; [Main] |
    |-------------------------------------------------------------------------------------|
    |400031B0|rtl60.bpl |System.pas | |Error | |
    |40002FF7|rtl60.bpl |System.pas | |_FreeMem | |
    |40002FE4|rtl60.bpl |System.pas | |_FreeMem | |
    |4000684C|rtl60.bpl |System.pas | |_LStrArrayClr | |
    |7C91E21D|ntdll.dll | | |ZwQueryVirtualMemory | |
    |7C80B83F|kernel32.dll | | |VirtualQueryEx | |
    |7C80B828|kernel32.dll | | |VirtualQueryEx | |
    |7C80B869|kernel32.dll | | |VirtualQuery | |
    |7C80B859|kernel32.dll | | |VirtualQuery | |
    |00E34546|BORLNDMM.DLL |Borlndmm.pas| |SysGetMem | |
    |00E344C3|BORLNDMM.DLL |Borlndmm.pas| |SysGetMem | |
    |4000F0A8|rtl60.bpl |Sysutils.pas| |FmtStr | |
    |4000F09E|rtl60.bpl |Sysutils.pas| |Format | |
    |4000F094|rtl60.bpl |Sysutils.pas| |Format | |
    |40012B84|rtl60.bpl |Sysutils.pas| |Exception | |
    |4000687C|rtl60.bpl |System.pas | |_LStrAsg | |
    |40012B8F|rtl60.bpl |Sysutils.pas| |Exception | |
    |00E346C7|BORLNDMM.DLL |Borlndmm.pas| |SysFreeMem | |
    |40002FE9|rtl60.bpl |System.pas | |_FreeMem | |
    |40002FE4|rtl60.bpl |System.pas | |_FreeMem | |
    |40006844|rtl60.bpl |System.pas | |_LStrClr | |
    |40006828|rtl60.bpl |System.pas | |_LStrClr |
    Je n'ai pas tout mis car c'est vraiment trop long !
    Avec ça je ne sais pas plus d'où viens mon exception...en tout cas je ne vois pas. Si vous trouvez une indication merci de me prévenir

  9. #9
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 407
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 407
    Par défaut
    Salut !

    Il doit y avoir un objet mal supprimé.
    Est-ce que ça peut venir de tes composants perso ?
    Tu dis que tu ne crées pas d'objets dynamiquement... ?

    A plus !

  10. #10
    Membre éprouvé

    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    1 163
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 163
    Par défaut
    Apparement j'ai trouvé : cela venait d'une des DLL home made que j'utilisait... Mais bon je comprend pas alors pourquoi l'erreur survient sur la ligne indiquée et pas sur celle où je décharge (et appelle une fonction dans la DLL pour tout détruire) la DLL.

    Merci tout de même pour votre aide.

  11. #11
    Membre Expert
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Billets dans le blog
    1
    Par défaut
    bonjour Gilles,
    je ne suis pas d'accord avec l'analyse que tu a faite l'évenement Onclose d'une Form est utilisé généralement dans les Applications MDI
    le paramètre Action permet de définir si la destruction de la fiche doit se poursuivre ou si la fiche doit par exemple être cachée
    aucune destruction d'élément n'a lieu dans cette évenement

    c'est naturellement dans le destructeur de la Form qu'a lieu la libération mémoire de la fiche
    c'est au programmeur de libérer les Objects creés mauellement
    la destruction de la fiche, ainsi que tous les composants descendants a lieu par une appel au destructeur de la classe de base TCustomForm

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    /* TCustomForm.Destroy */ inline __fastcall virtual ~TForm(void) { }
    de même la construction des Liste, (TList ou TStringList) doit se faire dans le constructeur de la Form et non pas dans FormCreate

    Avec mes meilleures Salutations
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  12. #12
    Membre Expert
    Avatar de Gilles Louïse
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    421
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2002
    Messages : 421
    Par défaut
    Merci DjmSoftware pour ces explications très claires.

    Il se trouve que j'ai plusieurs fois eu à mettre du code dans le OnClose plutôt que dans le OnDestroy, ce pourquoi j'utilisais l'expression "l'expérience montre" pour exprimer par là que je n'ai pas approfondi la question tout en remarquant ce fait.

    Déclarons un pointeur de TEdit dans la classe principale.

    Maintenant, dans le constructeur de la forme, je construis une centaine de TEdit ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    __fastcall TForm1::TForm1(TComponent* Owner)
       : TForm(Owner)
    {
    int i;
    for(i=0;i<100;i++)
       {
       e=new TEdit(Application);
       e->Parent=Form1;
       e->Tag=2*i+1;
       }
    }
    Ce n'est pas très beau car il n'y a qu'un seul pointeur mais on s'en fout, dans certaines applications, le Sender suffit sans compter qu'il est toujours possible de retrouver toutes les adresses. Le problème n'est pas là, il est que 100 objets ont été construits, on n'en verra certes qu'un car on n'a pas pris la peine de faire mouvoir les Left et Top.

    Si maintenant, j'invoque le Tag de e dans le OnDestroy qui doit normalement sans autre code pointer le dernier objet créé, j'ai une violation d'accès.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void __fastcall TForm1::FormDestroy(TObject *Sender)
    {
    int i=e->Tag;
    }
    Violation qui disparaît si j'écris ce même code dans le OnClose.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
    {
    int i=e->Tag;
    }
    J'en ai inféré à la longue que les objets étaient déjà détruits dans le OnDestroy (encore que si on n'en crée que 10 ça passe, allez savoir), ce qui m'empêchait de les utiliser encore alors que dans le OnClose, tous les objets ayant la forme principale pour propriétaire étaient encore disponibles.

    Je ne cherche pas du tout à vous contredire, ce n'est pas mon genre, je suis simplement plus pragmatique que théoricien, je m'occupe plus de faire marcher le plus vite possible (et mes patrons par le passé ont apprécié) même si je ne suis pas à même de fournir une explication. C'est très différent dans l'algorithmique car là vous maîtrisez tout alors qu'ici, en POO, on joue derrière vous et vous ne savez pas obligatoirement exactement ce qui se passe.

    Si maintenant je crée les objets ainsi

    l'erreur disparaît. Très difficile à voir si vous avez l'habitude d'utilisation la syntaxe avec Application. Pour ma part, je préfère utiliser Application et utiliser le OnClose s'il s'agit d'invoquer des composants. De même, si on doit déjà utiliser des composants sur la forme, il faut plutôt choisir le OnShow car il ne sont pas encore construits dans le constructeur de la classe principale. Maintenant, pour libérer la mémoire ordinaire, on utilise évidemment le OnDestroy prévu à cet effet.

    À bientôt
    Gilles

  13. #13
    Membre éprouvé

    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    1 163
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 163
    Par défaut
    C'est très bon à savoir cela gilles !
    Peut être que dans mes propres composant c'est une erreur du genre !

    Merci

  14. #14
    Membre Expert
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Billets dans le blog
    1
    Par défaut
    bonsoir Gilles,
    désolé de te contredire a nouveau
    <l'owner>< des composants creés statiquement dans une form lors de la conception est toujours la Form elle-même conteneur de ces composants et non pas l'object Application

    pour une raison inconnue a part des concepteurs de la VCL les composants crés avec comme Owner l'object Application sont détruits avant l'appel
    au destructeur de la dite Form

    il est a remarquer comme tu l'a démontré que suivant le nombre de composants creés avec comme Owner l'object Application ou peut-être de la mémoire disponible la destruction de ces composants s'effectuent bien dans le destructeur de la Form <FormDestroy>

    pour ma part pour éviter ces désagréments je préfère construire ces composants soit avec commme Owner la Valeur NULL et décider de libérer la mémoire associée dans le destructeur ou alors travailler de manière équivalente à la construction statique des composants en donnant comme Owner la valeur <this> a sovoir la Form elle- même ce qui garantit que ce s composants seront détruits dans le destructeur de la Form

    Cordialement
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  15. #15
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 407
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 407
    Par défaut
    Salut !

    Personnellement j'ai toujours pensé qu'il fallait respecter une certaine
    stratification en ce qui concerne la propriété, en tant que détention d'objets.
    - Application détient les forms
    - les forms détiennent leurs objets
    - un objet détenu par une form détient ses propres objets

    En tout cas, c'est ce qui semble bien se dégager du "blablabla conceptuel" autour
    de TComponent. D'ailleurs, on ne peut pas tout ramener vers Application, puisque
    MDIForm détient ses MDIChild (sauf erreur de ma part).

    Pour le cas de Neilos, je ne ne sais pas quand il libère sa dll, mais à mon avis
    il devrait le faire au moment ou rien n'est encore détruit, c'est à dire dans la
    OnClose (cas si caFree). En effet, cela lui garantit d'avoir des propriétaires
    valides (au cas où)
    car ensuite survient la OnDestroy.

    A plus !

  16. #16
    Membre éprouvé

    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    1 163
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 163
    Par défaut
    J'ai transféré tout mon code de libération des DLL et autres dans mon OnClose.
    Je n'ai pas trop le temps de me pencher sur ce problème en ce moment, mais il demeure. C'est assez variable en fait : parfois le bug se produit, parfois pas :S

    Je vais vérifier tous mes composants fait maison un à un.

  17. #17
    Membre Expert
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Billets dans le blog
    1
    Par défaut
    Bonjour,
    en principe les composants que tu crée dans une DLL ne doivent pas avoir d'OWNER valeur (NULL) ceci garanti que lors de la libération de la DLL les composants que tu a creés devront être détruit manuellement.

    Ex
    Composant principal Un Tpanel Owner NULL
    un TLAbel posé sur le Panel Owner Tpanel
    .....

    si tu a par exemple implémenté une classe dans une DLL
    tu peux utiliser le paramètre Reason de la fonction DLLMAin pour libérer le ou les composants


    Code pour la libération


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    switch (reason)
    {
      case DLL_PROCESS_ATTACH:// Instanciation du Composant ;
      break;
      case DLL_PROCESS_DETACH:// Libération du Composant;
      break;
    }
    les Composants creés avec comme owner la Form elle-même sont détruits après l'appel au destructeur de la classe de base ~TForm(void) ,ainsi que la Form elle-même

    Cordialement
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  18. #18
    Membre éprouvé

    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    1 163
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 163
    Par défaut
    Je me suis peut être mal exprimé mais mes composants ne sont pas dans ma DLL il sont directement dans mon programme.

    En fait mon programme fait appel à des DLL faites maisons (en fait des modules) et j'utilise directement dans mon programme des composants eux aussi fait maison.

    Bref les éventuels composants qui pourraient faire planter mon application sont dans un paquet.

    Merci quand même pour toutes ces précisions !

  19. #19
    Membre Expert
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Billets dans le blog
    1
    Par défaut
    bonjour,
    les paquets utilisent toujours les BPL VCL et RTL , ton application ,ainsi que tes DLL utilisent -elle aussi ces 2 Dll de borland ?
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  20. #20
    Membre éprouvé

    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    1 163
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 163
    Par défaut
    Hum, oui mes DLL les utilisent.
    Elles n'utilisent pas de fenêtre (donc pas de TForm)
    mais sont amenées à utiliser des TRegistry et des TStrings.

    Donc mon application pourrait crasher à cause d'un objet non libéré dans une des mes DLLs ?

    EDIT : précision, je crois (je suis en stage j'ai pas mon projet perso sous les yeux ) que les composants ne sont utilisé qu'au sein d'une fonction de ma DLL. Je veux dire qu'il n'y a pas de composant global.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 2
    Dernier message: 28/04/2010, 18h59
  2. Violation d'acces lors d'une destruction d'un composant
    Par Rayek dans le forum Composants VCL
    Réponses: 15
    Dernier message: 23/11/2005, 11h37
  3. requete / violation d'accès
    Par marie253 dans le forum Bases de données
    Réponses: 4
    Dernier message: 13/08/2004, 13h29
  4. Violation d'acces apres Execute
    Par SegmentationFault dans le forum Connexion aux bases de données
    Réponses: 6
    Dernier message: 10/08/2004, 16h23
  5. Violation d'accès apres Close
    Par SegmentationFault dans le forum Bases de données
    Réponses: 3
    Dernier message: 05/07/2004, 16h46

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