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

Langage Delphi Discussion :

Runtime error 216 à la fermeture de l'application


Sujet :

Langage Delphi

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 91
    Points : 54
    Points
    54
    Par défaut Runtime error 216 à la fermeture de l'application
    Bonjour,

    j'ai un problème de runtime 216 à la fermeture de mon application,
    lorsque j'utilise une dll.
    j'ai lu pas mal de chose à ce sujet sur ce forum, mais sans succès.

    cela viens à partir du moment où je met un Tbitbtn sur le form de la dll (un Tbutton simple fonctionne).

    je vous met le code (tout simple).

    code sur l'application:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    procedure start_contrat(name,pass,alias:AnsiString;HandleAppli : HWND); stdcall;external 'dll\Contrats.dll' name 'Start_Contrat';
    procedure free_contrat; stdcall;external 'dll\Contrats.dll' name 'Free_Contrat';
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    start_contrat(Uppercase(DMSphere.dbHotel.Username),DMSphere.dbHotel.Password,ParamStr(1),Application.Handle);
    free_contrat;
    code sur la dll

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      procedure start_Contrat(username,pass,alias:string;HandleAppli : HWND);stdcall;
      procedure free_contrat;stdcall;
    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
    procedure start_Contrat(username,pass,alias:string;HandleAppli : HWND);
    begin
    Application.Handle := HandleAppli;
    Application.CreateForm(TFContrat, FContrat);
    FContrat.Position := poScreenCenter;
    FContrat.Showmodal;
    end;
     
    exports Start_contrat name FUNC_DLL_CONTRAT;
     
      procedure free_contrat;
      begin
         FContrat.destroyform;
      end;
     
    exports free_contrat name FUNC_DLL_FREECONTRAT;
     
    destructor TFContrat.destroyform;
    begin
       FContrat.Free;
       FContrat := nil;
       inherited;
    end;

    Voila donc si je rajoute un bitbtn (par exemple) sur mon form, message runtime eror 216 quand je quitte l’application.
    merci d'avance.

  2. #2
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2012
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2012
    Messages : 92
    Points : 159
    Points
    159
    Par défaut
    je vais peut être dire une connerie, mais pourquoi des types différents pour name,pass,alias dans la procédure start_contrat ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    destructor TFContrat.destroyform;
    begin
       FContrat.Close; // le close libérera ta form
       inherited;
    end;

  3. #3
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 550
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 550
    Points : 3 916
    Points
    3 916
    Par défaut
    Grosse horreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    destructor TFContrat.destroyform;
    begin
       FContrat.Free;
       FContrat := nil;
       inherited;
    end;
    un destructeur pour une seule instance (FContrat) !! Un destructeur concerne toutes les instances, le code de la classe est mélangé avec le code concernant une instance en particulier, c'est pas clean. On peut l'imaginer pour une singleton mais on dirait que toute la mécanique n'y est pas.

    Mieux vaut reporter ces instructions dans free_contrat et éliminer la méthode destroyform, c'est une hérésie et une GROSSE source de problème car qui prouve qu'elle sera invoquée de manière sûre depuis une autre instance que FContrat ?

    @+

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 91
    Points : 54
    Points
    54
    Par défaut
    OK OK
    c’était pour tester une solution.
    dans ce cas la on met (testé avant mais marche pas)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
      procedure free_contrat;
      begin
       FContrat.Free;
       FContrat := nil;
      end;

  5. #5
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 550
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 550
    Points : 3 916
    Points
    3 916
    Par défaut
    Au lieu de FContrat.Free, as-tu essayé FContrat.Release ?

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  6. #6
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 671
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 671
    Points : 13 065
    Points
    13 065
    Par défaut
    Dès lors où Application est son propriétaire et est en cours de libération, FContact a de fortes chances d'être déjà détruite à l'appel de Free.
    Ces deux procédures ne sont pas bonnes. Il n'y a aucun intérêt à garder FContact après ShowModal puisqu'une nouvelle instance est systématiquement recréée.

  7. #7
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 550
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 550
    Points : 3 916
    Points
    3 916
    Par défaut
    Bien vu, perso, j'aime pas utiliser Application.CreateForm.
    Pour découpler la libération de la form dee celle de l'application, utilise le constructeur Create de la form et passe Nil en paramètre pour le propriétaire, ce sera alors à toi de garantir la libération de la fiche.

    Petit complément selon la doc Embarcadero :
    216 = Access violation EAccessViolation

    cf http://docs.embarcadero.com/products...rrors_xml.html

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 91
    Points : 54
    Points
    54
    Par défaut
    merci pour votre aide.

    j'ai essayé plusieurs méthode, j'ai toujours le même résultat.
    j'ai même enlevé le ".free".

    ce problème viens probablement du tbitbtn car s'il y est pas, j'ai pas de message d'erreur.

    pour précision le message viens à la fermeture de l'application complète.
    fermer le form de la dll ne donne pas de message d'erreur.

    et pour finir "petit oubli" cela n'arrive que sur windows XP.
    windows 7 ou 8 pas de problème.

  9. #9
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 429
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 429
    Points : 24 794
    Points
    24 794
    Par défaut
    Retire le Application.CreateForm et utilise le TFContrat.CreateEnsuite, tu utilises la DLL directement en external !
    Lorsque j'ai manipulé des TForm entre EXE et DLL, j'ai toujours utilisé un LoadLibrary et FreeLibrary, ainsi tu gères mieux la fin de vie de ta DLL

    Tu n'utilises qu'une seule fois start_Contrat, comme tu ne gère qu'une seule référence, plusieurs appels serait source d'erreur

    ton BitBtn a-t-il une image, peut-être un problème à ce sujet
    ou alors ferme tu l'appli sur un clic sur ce bouton ?
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 91
    Points : 54
    Points
    54
    Par défaut
    concernant le create j'ai testé sans resultat.

    et le loadlibrary aussi mais il passe jamais le if assigned

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    var
       handle: THandle;
       Start_contrat : procedure(name,pass,alias:Ansistring);
    begin
      Handle := LoadLibrary(pChar('dll/Contrats.dll'));
      if handle <> 0 then
      begin
        start_contrat := GetProcAddress(handle,pAnsichar('Start_contrat')); 
        if Assigned(start_contrat)  then 
        begin
    start_contrat(Uppercase(Username),Password,ParamStr(1),Application.Handle);    
        end;
        FreeLibrary(Handle);
      end;

  11. #11
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 550
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 550
    Points : 3 916
    Points
    3 916
    Par défaut
    Salut

    D'abord, inverser le slash :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Handle := LoadLibrary(pChar('dll/Contrats.dll'));
    d'où :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Handle := LoadLibrary(pChar('dll\Contrats.dll'));
    Puis utiliser l'@ :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    start_contrat := GetProcAddress(handle,pAnsichar('Start_contrat'));
    Essayer à la place :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @start_contrat := GetProcAddress(handle,pAnsichar('Start_contrat'));
    Rem : J'ai pas fait de test.

    @+

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 91
    Points : 54
    Points
    54
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        @start_contrat := GetProcAddress(handle,pAnsichar('start_contrat'));  
      if Assigned(@start_contrat)  then  
    start_contrat(Uppercase(Username),Password,ParamStr(1));
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        @start_contrat := GetProcAddress(handle,pAnsichar('start_contrat'));  
      if @start_contrat <> nil  then  
    start_contrat(Uppercase(Username),Password,ParamStr(1));
    j'ai essayé plusieurs code mais marche pas.

    j'ai pris exemple sur :
    http://delphi.developpez.com/faq/?page=systemedll

    visiblement le getprocAddress marche pas

  13. #13
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 671
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 671
    Points : 13 065
    Points
    13 065
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    exports Start_contrat name FUNC_DLL_CONTRAT;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @start_contrat := GetProcAddress(handle,pAnsichar('start_contrat'));
    Un des rares cas (si ce n'est le seul) où le texte est sensible à la casse
    Les transtypages PChar/PAnsiChar sont inutiles dans ce cas puisque 1) tu passes des constantes, 2) LoadLibrary/GetProcAddress acceptent de l'ANSI ou de l'Unicode

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @start_contrat := GetProcAddress(handle, 'Start_contrat');
    Attention aussi au chemin en relatif, relatif au répertoire de travail et non à celui de l'application. Préfère-lui un chemin absolu !

  14. #14
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    91
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 91
    Points : 54
    Points
    54
    Par défaut
    OK C'est bon.
    Donc il faut utiliser la méthode dynamique pour pas avoir de problème.

    Le GetProcAddress est effectivement sensible à la casse.

    merci à vous tous pour votre aide.

  15. #15
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 671
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 671
    Points : 13 065
    Points
    13 065
    Par défaut
    Le référencement statique fonctionne très bien aussi, mais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    procedure start_contrat(name,pass,alias:AnsiString;HandleAppli : HWND); stdcall;external 'dll\Contrats.dll' name 'Start_Contrat';
    ne correspond pas à

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    exports Start_contrat name FUNC_DLL_CONTRAT;

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Runtime Error 216
    Par Bernard B dans le forum Langage
    Réponses: 10
    Dernier message: 25/01/2012, 09h52
  2. [Free Pascal] Runtime error 216 - Pointeurs - Procédures - Unit
    Par ZeCaM dans le forum Free Pascal
    Réponses: 4
    Dernier message: 25/12/2009, 18h38
  3. Runtime error 216
    Par Kcintim dans le forum EDI
    Réponses: 7
    Dernier message: 18/02/2009, 00h42
  4. Réponses: 6
    Dernier message: 16/06/2006, 10h14

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