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++ Discussion :

Erreurs à la fermeture du programme


Sujet :

C++

  1. #1
    Membre habitué Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Points : 158
    Points
    158
    Par défaut Erreurs à la fermeture du programme
    Bonjour,

    J'ai écris une programme qui permet de passer une structure decrite en MIDL sur un serveur COM et de la récupérer après traitement.

    Le programme marche très bien jusqu'à l'arrêt du serveur. Quand je quitte le client, le serveur se ferme automatiquement, et là 3 erreurs Windows apparaissent (OxC0000005: Violation d'accès).

    Je ne peut pas me servir du debugueur puisque c'est le serveur qui plante.

    Cela fait quelques jours que je cherche, mais je ne trouve pas d'où ça vient.

    J'ai lu le tutorial sur la programmation dcom, mais je n'est pas tout saisi!!

    Le compteur de référence (changeant avec les appels de AddRef et Release) d'un objet COM est-il vraiment important? Peut-il donner ce genre d'erreurs? ou est-ce juste une aide pour le programmeur?

    Quelqu'un aurait-il une piste?

  2. #2
    Membre averti
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Points : 410
    Points
    410
    Par défaut
    Bonjour,

    Je ne connais pas du tout les applis/lib dont tu parles. Mais en général, lorsque j'ai eu des problèmes d'applications qui crashent à la fermeture, il s'agissait de problèmes de nettoyage de mémoire.

    En général, pour te prémunir de ce genre de problème, tu utilises des objets dédiés à la gestion de la mémoire, de type shared_ptr ou dataManager (par exemple)

    Mais quand tu utilises des librairies, cela peut aussi venir d'une mauvaise utilisation. J'ai déjà eu le problème avec ce genre de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     int tailleDunBufferQuelconque = 48;
    int endroitOuTuPoques = 48;
    donnees = fonction_d_une_lib_qui_entre_autre_reserve_de_la_memoire(tailleDunBufferQuelconque);
    fonction_d_une_lib_qui_utilise_les_donnees(donnees,endroitOuTuPoques);
    Ou la lib s'attend à ce que les deux entiers que tu utilisent aient une relation entre eux, comme (endroitOuTuPoques < tailleDunBufferQuelconque).

    C'est assez pénible à détecter. Et je ne connais pas d'outil qui fasse cela à ta place. Si quelqu'un en connait, merci à lui de partager son savoir qui serait bien utile.

    Ce que je ferais à ta place, c'est de désactiver les fonctionnalités de mon programme une par une, jusqu'à cela ne plante plus, et par dichotomie, je trouverais l'endroit ou cette allocation foireuse a lieu.

  3. #3
    Membre habitué Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Points : 158
    Points
    158
    Par défaut
    Le problème, c'est que ça ne plante pas toujours (malheureusement) et pas toujours au même endroit.

    Je vais quand même cherché de ce coté là, même si c'est déjà fait...

  4. #4
    Membre averti
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Points : 410
    Points
    410
    Par défaut
    Citation Envoyé par sylvain.cool Voir le message
    Le problème, c'est que ça ne plante pas toujours (malheureusement) et pas toujours au même endroit.
    "Pas toujours au même endroit", c'est plutôt fréquent avec ce type d'erreur. Et de fait, il ne faut pas chercher l'erreur au moment où le programme plante, mais bien au moment où elle a lieu.

    "Pas toujours", c'est peut-être une bonne nouvelle. Cela peut vouloir dire que l'erreur dans ton code n'a pas systématiquement lieu, autrement dit qu'elle dépend de l'utilisation d'une fonctionnalité particulière.

    Si tu as de la chance, l'erreur est dans une fonction que tu n'appelles pas toujours, mais dont tu peux savoir si tu l'appelles. Si c'est le cas, tu auras le début de ta solution lorsque tu auras trouvé la dite fonction.

    Si tu arrives à trouver une règle comme "cela plante à chaque fois que je génère une sortie xml de plus de 300 objets" ou "cela plante à chaque fois que je charge plus de 300 textures" ou "cela plante à chaque fois que je décharge le dernier son que j'ai chargé", tu auras le début d'une piste.

    Sinon, tu peux aussi vérifier tous tes appels de fonctions de librairies à la main si tu n'en a pas trop.

    Bonne chance

  5. #5
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par sylvain.cool Voir le message
    Je ne peut pas me servir du debugueur puisque c'est le serveur qui plante.
    Rien n'empêche d'accrocher un debuggeur au serveur... Sous VS, par exemple : Debug/Attach to process
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par sylvain.cool Voir le message
    Le compteur de référence (changeant avec les appels de AddRef et Release) d'un objet COM est-il vraiment important? Peut-il donner ce genre d'erreurs? ou est-ce juste une aide pour le programmeur?
    Oui, il est vraiment important.
    Si tu as peur de mal le gérer, n'hésite pas à utiliser des pointeurs intelligents (sous Visual, tu as les CComPtr<> de ATL, les _com_ptr_t<> du Compiler COM Support. Sinon, tu peux utiliser un boost::intrusive_ptr<> et définir des fonctions qui appellent addref() et release())...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre habitué Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Points : 158
    Points
    158
    Par défaut
    Donc, il faut absolument que je les gèrent.

    Côté client, tout va bien, mes compteurs sont bons.

    Mais côté serveurs, rien ne va plus. J'ai des chiffres bizarres.
    Du style je passe une interface qui a son compteur à 1 et en arrivant de l'autre côté, elle est à 3!!!

    Du coup j'ai du mal...

    Si j'ai bien compris, les erreurs peuvent venir de là?

  8. #8
    Membre habitué Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Points : 158
    Points
    158
    Par défaut
    Pour ce qui est du debugueur, j'ai réussi à attacher le processus, mais il ne me donne que le code CPU... ça ne me sert a rien!

  9. #9
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Et si le serveur est dans la même solution?

    Normalement, la gestion du comptage de référence est plus importante côté serveur. Mais n'oublie pas, dès qu'il y a du marshalling en jeu, il y a des proxys qui détiennent des références.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Membre habitué Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Points : 158
    Points
    158
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Si tu as peur de mal le gérer, n'hésite pas à utiliser des pointeurs intelligents
    Pour quoi faire exactement?

    Citation Envoyé par Médinoc Voir le message
    Mais n'oublie pas, dès qu'il y a du marshalling en jeu, il y a des proxys qui détiennent des références.
    Comment faire pour libérer ses références? Je fais plusieurs release en fin de programme (jusqu'à atteindre 0)?

  11. #11
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Pour libérer automatiquement la référence lors de la destruction du pointeur, sans se soucier des exceptions ou des return au beau milieu d'une fonction...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Membre habitué Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Points : 158
    Points
    158
    Par défaut
    J'utilise déjà des pointeurs intelligents. Et ça plante quand même.

    J'ai une interface dessus qui a 2 propriétés get et set sur une interface dessous. Voici le code de ces 2 propriétés :
    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
    24
    25
    26
    STDMETHODIMP TdessusImpl::get_varDessous(Idessous** Value)
    {
      try
      {
    	*Value = m_pDessous; 
      }
      catch(Exception &e)
      {
        return Error(e.Message.c_str(), IID_Idessus);
      }
      return S_OK;
    };
     
     
    STDMETHODIMP TdessusImpl::set_varDessous(Idessous* Value)
    {
      try
      {
    	m_pDessous = Value;
      }
      catch(Exception &e)
      {
        return Error(e.Message.c_str(), IID_Idessus);
      }
      return S_OK;
    };
    Et la déclaration de m_pDessous dans la CoClass :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    public:
     
    	dessous * m_pDessous;
    En gros, quand je fais ceci, ça plante pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	TCOMIdessous dessousTest = Codessous::Create();
    	dessousTest->set_nb(12);  
     
    	TCOMIdessus dessusTest = Codessus::Create();
    	dessusTest->set_varDessous(static_cast<dessous*>(dessousTest));
    Et quand je rajoute ceci, j'ai mes 3 erreurs windows à la fermeture du serveur (qui se ferme automatiquement quand le client à libérer ses interfaces) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	TCOMIdessous varTest;
    	dessusTest->get_varDessous(&varTest);
    Les objets TCOMIXXX sont des pointeurs intelligents. Si je fais des release dessus, le programme plante. Normal puisque ils se détruisent au release et qu'en fin de programme il veut encore les détruire, mais ils n'existent plus.

    Là, je ne sais plus trop où chercher.
    Une idée? des pistes?

  13. #13
    Membre averti
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Points : 410
    Points
    410
    Par défaut
    Pour ma part, je suis un peu perdu.

    Quand tu dis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    TCOMIdessous dessousTest = Codessous::Create();
    ...
    dessusTest->set_varDessous(static_cast<dessous*>(dessousTest));
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    STDMETHODIMP TdessusImpl::set_varDessous(Idessous* Value)
    Veux-tu dire que IDessous* et dessous* sont en fait le même type ?
    Comment le type en question est-il relié à TCOMIdessous ?

    Quant tu dis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    TCOMIdessous varTest;
    dessusTest->get_varDessous(&varTest);
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    STDMETHODIMP TdessusImpl::get_varDessous(Idessous** Value)
    Veux-tu dire que TCOMIdessous est le type Idessous* ?

    Si c'est le cas, et si IDessous* égale dessous*, à quoi te sert le static_cast ?

    Enfin bref .. je suis un peu perdu dans ton code.

  14. #14
    Membre habitué Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Points : 158
    Points
    158
    Par défaut
    Idessous est une interface DCOM, c'est une classe virtuelle.

    dessous est la CoClass correspondante qui est elle implémentable (c'est là où sont codés les fonctions de l'interface).

    Coté client, j'utilise les classe TCOMIdessous. Ce sont des pointeurs intelligents qui héritent de la CoClass dessous et qui contiennent les méthodes permettant de créer et gérer des objets à distance.

    C'est clair ou je m'exprime mal?

  15. #15
    Membre averti
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Points : 410
    Points
    410
    Par défaut
    Citation Envoyé par sylvain.cool Voir le message
    Idessous est une interface DCOM, c'est une classe virtuelle.

    dessous est la CoClass correspondante qui est elle implémentable (c'est là où sont codés les fonctions de l'interface).

    Coté client, j'utilise les classe TCOMIdessous. Ce sont des pointeurs intelligents qui héritent de la CoClass dessous et qui contiennent les méthodes permettant de créer et gérer des objets à distance.

    C'est clair ou je m'exprime mal?
    Ne t'inquiètes pas, c'est probablement très clair, et c'est moi qui ne suis pas assez malin pour comprendre.

    Est-ce que tu viens de dire que TCOMIdessous hérite de dessous qui hérite de Idessous ?
    Parce que si c'est le cas, je ne comprends pas que tu donnes TCOMIdessous* à manger à ta fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    STDMETHODIMP TdessusImpl::get_varDessous(Idessous** Value)

  16. #16
    Membre habitué Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Points : 158
    Points
    158
    Par défaut
    La, je n'ai pas le choix. Tout est effectué automatiquement par des wizards. Je donne le nom de la CoClass et les propriétés de mon interface.

    De là, C++Builder me génère le code correspondant. Toutes les interface sont géré à partir de pointeurs, simple pour un argument en entrée et double pour un argument en sortie.

    TCOMIdessous hérite de la CoClass dessous, qui hérite de l'interface Idessous. Mais c'est plus compliqué que ça. C'est dans le code généré et c'est pas simple la-dedans!

  17. #17
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par sylvain.cool Voir le message
    J'utilise déjà des pointeurs intelligents. Et ça plante quand même.

    J'ai une interface dessus qui a 2 propriétés get et set sur une interface dessous. Voici le code de ces 2 propriétés :
    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
    24
    25
    26
    STDMETHODIMP TdessusImpl::get_varDessous(Idessous** Value)
    {
      try
      {
    	*Value = m_pDessous; 
      }
      catch(Exception &e)
      {
        return Error(e.Message.c_str(), IID_Idessus);
      }
      return S_OK;
    };
     
     
    STDMETHODIMP TdessusImpl::set_varDessous(Idessous* Value)
    {
      try
      {
    	m_pDessous = Value;
      }
      catch(Exception &e)
      {
        return Error(e.Message.c_str(), IID_Idessus);
      }
      return S_OK;
    };
    Et la déclaration de m_pDessous dans la CoClass :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    public:
     
    	dessous * m_pDessous;
    Ce n'est pas du tout "intelligent", ça. Tes fonctions ne suivent pas les règles de COM, elles doivent faire un AddRef() sur le pointeur retourné et le pointeur reçu. Le TCOMIdessous ne le fera pas à ta place, car il s'attend à ce que get_varDessous() l'ait déjà fait.

    Code C++ corrigé : 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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    STDMETHODIMP TdessusImpl::get_varDessous(Idessous** Value)
    {
    	//Value est en sortie pure, on n'est donc pas censé faire un Release() dessus.
    	assert( Value != NULL );
    	if(Value == NULL)
    		return E_POINTER;
    	assert( *Value == NULL );
    	//Ici, pas de test de *Value hors débogage
    	try
    	{
    		*Value = m_pDessous; 
    		(*Value)->AddRef();
    	}
    	catch(Exception &e) // la référence ne devrait-elle pas être const?
    	{
    		return Error(e.Message.c_str(), IID_Idessus);
    	}
    	return S_OK;
    };
     
     
    STDMETHODIMP TdessusImpl::set_varDessous(Idessous* Value)
    {
    	try
    	{
    		//m_pDessous est un pointeur bète, il faut faire le release soi-même
    		dessous * pRelease = m_pDessous;
    		m_pDessous = Value;
    		if(m_pDessous != NULL)
    			m_pDessous->AddRef();
    		if(pRelease != NULL)
    			pRelease->Release();
    	}
    	catch(Exception &e)
    	{
    		return Error(e.Message.c_str(), IID_Idessus);
    	}
    	return S_OK;
    };
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  18. #18
    Membre habitué Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Points : 158
    Points
    158
    Par défaut
    Ah ben comme ça, ça marche très bien.

    J'avais pas très bien compris ce que j'avais lu sur le net.

    Encore une fois, tu es mon sauveur!

    Merci beaucoup Médinoc.

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 08/11/2010, 17h08
  2. Réponses: 3
    Dernier message: 23/09/2009, 17h30
  3. Réponses: 2
    Dernier message: 17/10/2008, 15h56
  4. une Erreur à la fermeture du programme
    Par Dr_shaman dans le forum VB.NET
    Réponses: 8
    Dernier message: 03/07/2008, 16h41
  5. gestion d'erreur et fermeture recordset
    Par yorra dans le forum Access
    Réponses: 4
    Dernier message: 14/11/2004, 11h38

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