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

Segfault bizarre avec delete


Sujet :

Langage C++

  1. #1
    Membre éclairé Avatar de Darktib
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 66
    Par défaut Segfault bizarre avec delete
    Bonjour,

    Je suis en train de programmer un jeu vidéo de stratégie, et actuellement le dev est en pause à cause d'un crash dur à corriger.

    plateforme
    - Visual Studio 2008
    - Windows XP

    Dans la boucle du jeu, les unités sont mises à jour; certaines peuvent etre 'tuées', et s'ajoutent alors à une liste de pointeurs contenant, toutes les unités à supprimer. Cette suppression est effectuée juste après la mise à jour des unité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
     
    	// update entities
    		for(int t = 0; t < 8; t++)
    			if(entities[t])
    				entities[t]->updateEntity(deltaT);
     
    		// search for deleted entities
    		while(deletionQueue.begin() != deletionQueue.end())
    		{
    			game::Entity* entt = *deletionQueue.begin();
    			if(entt)
    			{
    				printf("deleting 0x%p...",entt);
    				delete entt;
    				for(int t = 0; t < 8; t++)
    					if(entities[t] == entt)
    						entities[t] = 0;
    				if(selectedEntity == entt)
    					selectedEntity=0;
    			}
    			deletionQueue.erase(deletionQueue.begin());
    		}
    Le problème, c'est que ca crashe. Le crash n'est pas systématique, arrive en général après 1 ou 2 suppression(s); j'ai utilisé le débuggueur de VC++. Arrivé sur la ligne 'delete entt', segfault immédiate: les destructeurs ne sont même pas appelés, j'ai l'impression que c'est l'adresse même de l'opérateur delete qui est mauvaise... De temps en temps l'unité est déjà supprimée avant le delete (je ne sait pas pourquoi, y pas beaucoup de delete dans mon code surtout au niveau des unités), mais la plupart du temps l'unité à supprimer est bien présente en mémoire, sans aucun problème, je peut y accéder avec visual studio par exemple.

    En bref, je sais juste que c'est le delete qui plante, mais pas pourquoi



    Merci d'avance pour votre aide,

    ~Darktib

    edit: j'ai essayé avec gcc... il n'y a pas de crash, par contre y des tas de petits bugs partout...et qui n'apparaissent qu'avec ce compilo

    edit2: en réessayant (sans avoir recompilé), je suis tombé sur une autre erreur (mais pour le même crash..), au lieu d'une violation d'accès mémoire, windows m'a balancé une "Privileged Instruction", et avec du googling j'ai vu que ca viendrait d'une corruption de la pile... à confirmer, je recherche un peu plus.

  2. #2
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 545
    Par défaut
    Bonjour,

    Citation Envoyé par Darktib Voir le message
    edit: j'ai essayé avec gcc... il n'y a pas de crash, par contre y des tas de petits bugs partout...et qui n'apparaissent qu'avec ce compilo
    des petits bugs, vous voulez dire des messages d'erreur/warning ? donnez des exemples

    si vous arrivez néanmoins à compiler la chose avec g++ sous Linux je vous conseille de regarder ce qui se passe en lançant l'exécution avec valgrind
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  3. #3
    Membre éclairé Avatar de Darktib
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 66
    Par défaut
    Merci de votre réponse.

    Pour le compilo: mingw.

    Le bugs ne sont pas des bugs lors de la compilation, mais en cours d'exécution, du genre des comportements indéterminés... Le mieux serait que je puisse rester sous visual studio.

    Sinon, j'ai regardé au niveau assembleur et j'ai vu qu'à un moment, delete appelle le destructeur (il fait un call edx) - mais ce après deux trois opérations. Et il se trouve que assez souvent, le registre edx à l'air de contenir n'importe quoi; du coup le destructeur n'est pas appelé, et le code saute n'importe ou... pour me donner une belle privilegied instruction. Sans doute une corruption de la pile, ou de l'objet ? Et si c'est le cas, comment voir où arrive cette corruption ?

    J'ai aussi essayé PageHeap; cependant, ca n'a rien donné...

  4. #4
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 545
    Par défaut
    ce qui est certain c'est que vous avez du jardinage mémoire, et cela à beau être le printemps c'est pas bien

    si vous ne pouvez vraiment pas compiler/exécuter la chose sous Linux via valgrind peut être pouvez-vous modifier votre code en remplaçant tous vos delete de game::Entity par un ajout dans une liste, et à chaque fois vous regardez si par hasard vous n'avez pas déjà détruit la chose ? Évidemment cela ne marche que pour les deletes explicites, et votre problème de corruption mémoire vient peut être d'ailleurs
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  5. #5
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    Pourquoi se bouffer des pointeur et delete par dizaines ? RAII en force !!!!
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  6. #6
    Membre éclairé Avatar de Darktib
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 66
    Par défaut
    @bruno_pages : j'ai effectué ce que vous dites. Il se trouve qu'il n'y a que deux delete qui détruisent des entités dans tout le code pour l'instant.
    Et aucune entité n'est supprimée deux fois...

    @davidbrcz : Où appliquer du RAII ici ? Les entités doivent pouvoir etre créees/détruites à la volée, etc...


    Sinon, comment voir si un objet à été corrompu ?

    edit: précision, j'utilise Irrlicht et Boost, mais je ne pense pas que ca influe tant que ca.

  7. #7
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 545
    Par défaut
    le seul moyen que je connaisse pour vérifier la mémoire à l'exécution c'est encore une fois valgrind. Je ne sais pas si il y a un équivalent sous Windows ou si valgrind est compatible avec mingw, faites une recherche
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Citation Envoyé par Darktib Voir le message
    @davidbrcz : Où appliquer du RAII ici ? Les entités doivent pouvoir etre créees/détruites à la volée, etc...
    Quand tout le reste échoue, utilise des shared_ptr. Ou des intrusive_ptr.
    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.

  9. #9
    Membre éclairé Avatar de Darktib
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 66
    Par défaut
    Mais apparemment ca n'est pas un problème de pointeurs, vu qu'a chaque fois que je teste leur valeurs, elles sont bonnes...

    Sinon, j'ai testé en remplaçant les new/delete par mes propres fonctions:
    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
    game::Entity* new_e_func(game::SystemsReferences* s, game::Database* d)
    {
    	game::Entity* ptr = 0, *ptr2 = 0;
    	ptr = (game::Entity*)malloc(sizeof(game::Entity));
    	if(!ptr)
    	{
    		printf("Failed to allocate entity\n");
    		return 0;
    	}
    	ptr->game::Entity::Entity(s,d);
    	ptr2 = ptr;
    	printf("Allocated entity at 0x%p\n",ptr2);
    	return ptr;
    }
    void delete_e_func(game::Entity* e)
    {
    	if(!e)
    	{
    		printf("Cannot delete entity at 0x00000000\n");
    		return;
    	}
    	game::Entity* ptr = e;
    	e->game::Entity::~Entity();
    	free(e);
    	printf("Entity freed at 0x%p\n",ptr);
    }
    Et là, plus aucun crash, et pas de bugs.

    Avec tout ca (pas de crashs sur gcc, pas de crash avec malloc/free), j'en déduis que ca pourrait venir de l'implémentation de new/delete dans Visual Studio, qui serait peut être plus stricte au niveau des erreurs... (ca vient de toute façon de mon code et pas de l'implémentation de vs)

    edit:
    le code asm incriminé est:
    Code asm : 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
     
    				delete entt;
    004588F4  mov         eax,dword ptr [entt] 
    004588FA  mov         dword ptr [ebp-610h],eax 
    00458900  mov         ecx,dword ptr [ebp-610h] 
    00458906  mov         dword ptr [ebp-61Ch],ecx 
    0045890C  cmp         dword ptr [ebp-61Ch],0 
    00458913  je          0045893A 
    00458915  mov         esi,esp 
    00458917  push        1    
    00458919  mov         edx,dword ptr [ebp-61Ch] 
    0045891F  mov         eax,dword ptr [edx] 
    00458921  mov         ecx,dword ptr [ebp-61Ch] 
    00458927  mov         edx,dword ptr [eax] 
    // C'est cette ligne qui plante, lorsque edx pointe vers n'importe quoi (alors qu'il est sensé pointer vers le destructeur de game::Entity) :
    00458929  call        edx
    0045892B  cmp         esi,esp 
    0045892D  call        @ILT+5690(__RTC_CheckEsp) (45163Fh) 
    00458932  mov         dword ptr [ebp-0DF8h],eax 
    00458938  jmp         00458944 
    0045893A  mov         dword ptr [ebp-0DF8h],0 
    			}
    			deletionQueue.erase(deletionQueue.begin());
    00458944  lea         eax,[ebp-5F8h]

    Je ne connais pas l'asm, mais il me semble que ce code est sensé récupérer l'adresse du destructeur à partir du pointeur entt. Il y a des informations de débug pour situer ce code. Sinon, je vais essayer d'y aller en pas à pas dans cette zone pour bien comprendre le mécanisme.

  10. #10
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    J'ai lu en diagonal, mais détruits-tu des objets de façon polymorphe avec des destructeurs non virtuels ? Cf F.A.Q : Pourquoi le destructeur d'une classe de base doit être public et virtuel ou protégé et non virtuel ? et Pourquoi et quand faut-il créer un destructeur virtuel ?

  11. #11
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 545
    Par défaut
    Citation Envoyé par Darktib Voir le message
    j'en déduis que ca pourrait venir de l'implémentation de new/delete dans Visual Studio
    non, on peut juste en déduire que l'utilisation de la mémoire n'est pas la même

    ce n'est pas parce que cela ne crash plus que tout va bien, simplement l'effet n'est pas le même

    le code suivant ne crash pas et affiche bien 123, cela ne veut pas dire qu'il est correct :
    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
    #include <iostream>
    using namespace std;
     
    class C {
      public: int i;
    };
     
     
    int main(int, char **)
    {
      C * c = new C;
     
      delete c; // !!!
     
      c->i = 123;
     
      cout << c->i << endl;
     
      return 0;
    }
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  12. #12
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    je fais une petite digression concernant un point particulier dans ce code : est-il possible/safe d'utiliser un pointeur après avoir appliquer un delete dessus ?

    Car je lis ceci sur MSDN, concernant l'opérateur delete dans Visual C++ :

    If the operand to the delete operator is a modifiable l-value, its value is undefined after the object is deleted.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Non seulement il n'est pas safe de le déréférencer, mais d'après la norme, il n'est même pas safe de le lire! La norme n'interdit pas une architecture où le seul fait de charger un pointeur invalide dans un registre entraînerait une erreur hardware.

    Donc, de manière portable, tout ce qu'on peut faire sur un pointeur après un delete, c'est le mettre à 0/NULL/nullptr.
    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.

  14. #14
    Invité
    Invité(e)
    Par défaut
    (Je ne parlais bien sur pas de le déréférencer mais de le lire!)
    Donc il faudrait modifier le code de Darktib pour éviter les tests après le delete:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(entities[t] == entt)

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    En théorie, oui.
    Mais bon, sur les architectures les plus utilisées en ce moment, ça n'est pas si grave.
    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.

  16. #16
    Membre éclairé Avatar de Darktib
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 66
    Par défaut
    Pour le destructeur : pour avoir testé en pas a pas le code asm, il s'avère que ca crashe avant d'appeler le destructeur. Le programme n'arrive pas à récupérer l'adresse du destructeur, et saute n'importe ou.
    game::Entity dérive d'une classe dont le destructeur est bien virtuel(il s'agit d'ailleurs de la seule fonction virtuelle de la classe de base). game::~Entity n'est pas virtuel, et le fait de le mettre en virtuel ne changera rien.

    Pour l'équivalent de valgrind : soit des trucs très chers par IBM et Intel, sinon il y a Application Verifier, de Microsoft, qui est gratuit et pas mal (mais un peu moins riche je pense)

    EDIT: Je ne pensais pas que ca serait si important, mais apparemment ca pourrait être la cause de la corruption mémoire : les game::Entity utilisent un système de référencage qui les stockent dans une liste. Jusque ici, pas de problème, une liste de pointeurs *intelligents*, les références étant automatiquement supprimées lors de la suppression d'une entité. Seulement, cette liste est intrusive (from boost)... J'ai changé le mode de cette liste de 'normal_link' à 'safe_link'. Et là, je me prend une assertion(BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT) comme quoi les algos de cette liste ne sont pas initialisés; peut être que ca viendrait de là. Je fais plus de recherches.

  17. #17
    Membre éclairé Avatar de Darktib
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 66
    Par défaut
    J'ai trouvé la cause de l'erreur - du moins je pense : cela ne vient pas de mon code, mais de la fonction boost::intrusive::detail::member_hook_traits::to_not_ptr qui renvoie des valeurs erronées, et comme apparemment la fonction est bonne, ca à l'air d'etre le compilo, ce qui m'étonne beaucoup.

    La fonction qui pose problème (boost/intrusive/detail/utility.hpp):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
       static node_ptr to_node_ptr(reference value)
       {
          return reinterpret_cast<node*>(&(value.*P));
       }
    En essayant de manuellement récupérer le pointeur, j'obtiens un pointeur correct; avec le debuggueur, je constate que ptr2 = ptr + 4 ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ERSList::node_ptr ptr = ReferencedBy.get_real_value_traits().to_node_ptr(*toRef);
    ERSList::node_ptr ptr2 = static_cast<ERSList::node*>(&toRef->ERSMemberHook);
    Je ne sais pas comment corriger cette erreur, quelqu'un a t il une idée ?

  18. #18
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Tu dois avoir mis le pointeur avec un certain type statique et essayer de le récupérer avec un type statique parent (ou dérivée). Le reinterpret_cast fait la conversion en bourrin. Tu devrais le récupérer avec le même type puis faire un static ou dynamic_cast vers ton type cible.

  19. #19
    Membre éclairé Avatar de Darktib
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 66
    Par défaut
    Je ne contrôle pas la fonction to_node_ptr, elle fait partie de boost. Et l'appel présenté n'est que pour exemple.

    J'ai toutefois résolu le problème. Après avoir passé des heures à essayer de comprendre pourquoi il y avait un problème avec to_node_ptr, j'ai choisi de me coder une petite liste intrusive. Concrètement, il n'y avait qu'a rajouter 3 pointeurs et virer Boost.Intrusive . Et il se trouve que ca marche maintenant très bien, sans crash ni bugs.

    Certes, ce que j'ai codé n'est pas templatisé ni aussi puissant, c'est pas évolutif. Mais c'est plus adapté à mes besoins et beaucoup plus facile à comprendre, donc à débugguer s'il y avait un problème. Et c'est stable.

    Merci à tous pour votre aide.

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

Discussions similaires

  1. Erreur avec DELETE !
    Par James64 dans le forum Langage SQL
    Réponses: 18
    Dernier message: 25/10/2005, 10h49
  2. Problème très bizarre avec COUNT
    Par Nomade95000 dans le forum Langage SQL
    Réponses: 4
    Dernier message: 13/10/2005, 14h12
  3. [SWING] Exception bizarre avec Thread
    Par Gob4 dans le forum Débuter
    Réponses: 2
    Dernier message: 13/09/2005, 21h55
  4. [C#] Truc bizarre avec DataSet
    Par bendj dans le forum ASP.NET
    Réponses: 15
    Dernier message: 13/07/2005, 19h51
  5. problèmes bizarres avec jdbc
    Par jaimepasteevy dans le forum PostgreSQL
    Réponses: 8
    Dernier message: 12/12/2003, 12h00

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