1. #1
    Futur Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    avril 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 18
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : avril 2017
    Messages : 11
    Points : 8
    Points
    8

    Par défaut problème d'impression d'une chaine de caractère

    Bonjour, alors voilà je bloque sur un truc sûrement très idiot, mais je ne vois pas d'où peut provenir mon erreur. De mon malloc peut-être ? Ceci étant le premier code que je pond avec les fonctions malloc et free, ça me parait plus que vraisemblable. Donc avant de vous balancer les lignes de codes, je m'explique :
    Mon programme doit simplement me ressortir les informations donnés à l'execution de celui-ci. Par exemple si je l'execute avec "./a.out la li", il me ressort "./a.out\nla\nli".
    Voici le code :
    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    #include <stdlib.h>
     
    char *sum_params(char argc, char **argv)
    {
    	char *dest;
    	int strlen;
    	int i;
    	int j;
    	int o;
     
    	strlen = 1;
    	i = 0;
    	j = 0;
    	o = 0;
     
    	while (i < argc)
    	{
    		strlen = strlen + my_strlen(argv[i]) + 1;
    		i++;
    	}
     
    	i = 0;
    	dest = malloc(sizeof(char) * strlen);
    	free(dest);
     
    	while (o < strlen)
    	{
    		dest[o] = argv[j][i];
    		//my_putchar(dest[o]);
    		i++;
    		o++;
    		if (i > my_strlen(argv[j]))
    		{
    			dest[o] = '\n';
    			//my_putchar(dest[o]);
    			o++;
    			j++;
    			i = 0;
    		}
    	}
     
    	//my_putstr(dest);
    	return (dest);
    }
     
    int main(int ac, char **av)
    {
    	my_putstr(sum_params(ac, av));
    	my_putchar('\n');
    	return (0);
    }
    Voilà. Au début j'ai aussi pensé que mon erreur pouvait venir de mon "my_putstr()", mais j'ai essayé avec "my_putstr("Salut\nCaVa")", et tout m'est ressorti...
    Merci d'avance pour vos réponses !

    EDIT : J'ai aussi essayer de voir si ma chaine de caractère fonctionnait bien, et si ma boucle faisait de même, j'ai donc mis mes "my_putchar(dest[o])" dans la boucle, le plus étrange (enfin pour moi) c'est que ça m'a bien ressorti tous les caractères manquant à la fin...
    EDIT' : J'ai même tenté de voir si mon int strlen, utilisé dans mon malloc() était correct, et il l'est ! Je ne comprends vraiment pas là
    EDIT'' : Ne faites pas attention au "my_" devant strlen(), et putchar() et putstr(), c'est juste que j'utilise ma propre bibliothèque, pédagogiquement, c'est bien plus interessant d'utilisé ses propres fonctions. Vous devez simplement savoir que putstr() me ressort un string sur le terminal, et putchar(), un unique caractère. Même si ça semble évident, je le précise, on ne sait jamais ...

  2. #2
    Membre émérite
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    décembre 2015
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : décembre 2015
    Messages : 478
    Points : 2 263
    Points
    2 263

    Par défaut

    Bonjour,
    * libérer le buffer alloué immédiatement après l'allocation et avant de s'en servir est une très très mauvaise idée.
    * l'insertion du \n doit se faire quand on est la taille de la chaîne, pas après.
    * la chaîne construite doit se terminer par un \0 qui manque.

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    5 706
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 5 706
    Points : 15 602
    Points
    15 602
    Billets dans le blog
    1

    Par défaut

    Bonjour

    Déjà remarques générales: évite de nommer tes variables avec un nom correspondant déjà à une fonction. La fonction strlen() existe et a une action précise (qui en plus me parait identique à ta fonction my_strlen()). Bref ça évite les confusions. Idem avec tes variable "i", "j" et "o". Essaye d'utiliser des noms plus appropriés. "i" et "j" servent en général pour itérer rapidement des boucles quand leur nom n'a pas d'autre utilité mais si ces variables ont une signification plus profonde (comme "j" qui compte tes arguments) alors donne leur un nom plus explicite.
    De même "argc" et "argv" sont des noms conventionnellement associés aux paramètres de "main()". Ca aurait donc été plus logique qu'ils se nommassent ainsi dans le main() et "ac" et "av" dans ta fonction "sum_params".

    Autre remarque: la boucle
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    i=0;
    len=0;
    while (i < argc)
    {
    	len = len + strlen(argv[i]) + 1;
    	i++;
    }

    s'écrira plus facilement
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for (len=0, i=0; i < argc; i++)
    	len=len + strlen(argv[i]) + 1;   // Eventuellement len+=strlen(argv[i]) + 1 si tu connais les priorités des opérateurs
    (tu n'es pas obligé d'initialiser "len" dans le for() mais ça montre aux lecteurs que "len" et "i" vont ensemble)

    Autrement, si tu ne peux pas remplacer un while() par un for() (comme le second où "o" est incrémenté parfois deux fois) alors écris l'initialisation de ta variable juste avant le while. Ca évitera à tes copains (je pense que tu comptes programmer un jour en équipe) de faire le yoyo pour vérifier que "o" est bien à 0.

    Concernant ton algorithme, tu fais une grosse erreur ici if (i > my_strlen(argv[j])). Si tu réfléchis bien, tu comprendras que tu dois ajouter le '\n' au-moment où "i" a atteint la taille du mot et non quand il la dépasse. Ben oui, les indices commencent à 0. Donc si ton mot fait (par exemple) une seule lettre, tu stockes la lettre[0] dans dest[0] puis "i" passe à 1 et là il a atteint la taille du mot donc là tu rajoutes le '\n" !!!

    Ensuite tu oublies 1) de réserver la taille pour le '\0' et 2) de mettre ce '\0' à la fin de ta boucle. Donc ton tableau "dest" n'est pas une chaine. Donc tu n'as pas le droit de l'afficher via puts(). Accessoirement ton cahier des charges précise que si tu l'executes avec "./a.out la li", il doit te ressortir "./a.out\nla\nli" mais ton algo écrit, lui, "./a.out\nla\nli\n". Détail mineur mais c'est à toi de voir.

    Mais ta plus grosse erreur est ce malloc()+free(). Là je ne sais que te dire. Es-tu certain de savoir à quoi sert free() ???

    PS: sinon ton idée est bonne. J'ai copié ton code chez-moi, l'ai corrigé et il fonctionne.
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  4. #4
    Futur Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    avril 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 18
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : avril 2017
    Messages : 11
    Points : 8
    Points
    8

    Par défaut

    Super merci beaucoup j'ai compris mon erreur, il me manquait effectivement un '\0', mais je pensais que par défaut, après un free(), chaque "case" de la mémoire était un '\0', donc pour moi il n'y avait pas besoin de précisé à la fin ce '\0'.
    Cependant je pense que je n'ai pas très bien compris l'utilité de free(), je pensais que c'était simplement pour "libéré", remettre en 'NULL', des parties de la mémoire (oui j'ai dit précédemment que je pensais que ça devenait '\0', mais j'ai bien compris que ça ne l'était pas, du coup je suppose que ça devient 'NULL' ?). M'enfin bon, de toute façon je vais me replongé dans le man et faire quelques exercices pour être sûr de bien avoir compris son utilité.

  5. #5
    Responsable Modération
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    septembre 2007
    Messages
    6 770
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2007
    Messages : 6 770
    Points : 21 058
    Points
    21 058

    Par défaut

    Bonjour,

    Citation Envoyé par Deezio Voir le message
    Cependant je pense que je n'ai pas très bien compris l'utilité de free(), je pensais que c'était simplement pour "libéré", remettre en 'NULL', des parties de la mémoire (oui j'ai dit précédemment que je pensais que ça devenait '\0', mais j'ai bien compris que ça ne l'était pas, du coup je suppose que ça devient 'NULL' ?).
    malloc() sert à « allouer » de la mémoire, c'est-à-dire à en réserver officiellement l'usage au processus qui l'a demandé, à l'exclusion des autres. Par définition, sur un ordinateur, toute la mémoire est immédiatement disponible et fonctionnelle dès la mise sous tension. En théorie, on pourrait écrire là où ça nous chante, ça ne gênerait personne tant que l'on travaillerait seul. Seulement, à partir du moment où d'autres processus fonctionnent en parallèle et, même sur des mêmes monotâches, s'il y a des ressources conservés en arrière-plan, il faut bien que le système tienne une sorte de « plan d'occupation des sols » pour savoir quelles sont les zones qui sont actuellement utilisées et lesquelles ne le sont pas.

    Quand on a fini, on appelle free() (dans le sens du verbe « libérer ») pour marquer cette plage comme à nouveau disponible et qu'elle puisse éventuellement être ré-allouée à un autre processus. Il s'agit donc simplement de gérer la réservation de la mémoire. En soi, ces fonctions n'ont donc pas vocation à modifier son état et tu la trouves donc dans l'état où on l'a laissé.

    « NULL », en revanche, est une macro définie par les headers du C (avec #define) et qui vaut en principe 0, mais qui sert surtout de marqueur spécial utilisé de la même façon que son homologue en SQL : il s'agit simplement de dire que la valeur n'existe pas du tout ou est indéfinie. C'est généralement ce qu'on utilise par défaut quand on déclare et initialise un nouveau pointeur, ou quand une fonction censée renvoyer un pointeur est dans l'incapacité de le faire, par exemple quand malloc() est à court de mémoire et qu'elle ne peut donc pas renvoyer un pointeur vers la zone fraîchement allouée.

  6. #6
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    5 706
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 5 706
    Points : 15 602
    Points
    15 602
    Billets dans le blog
    1

    Par défaut

    Citation Envoyé par Deezio Voir le message
    il me manquait effectivement un '\0',
    Pas que ça. Ca c'est un détail minime. L'erreur principale de ton algo c'est ton test pour déterminer à quel moment mettre le '\n'.

    Citation Envoyé par Deezio Voir le message
    je pensais que c'était simplement pour "libéré", remettre en 'NULL'
    Libérer exactement. Donc imagine ce qui se passe si par exemple tu arrives dans un bus (bondé), que tu réserves une place puis que tu la libères à la seconde suivante et que tu pars te promener dans le fond du bus pendant 10mn puis que tu reviens essayer de te rasseoir à ta place...
    En ce qui concerne "remettre à NULL" pourquoi se fatiguer à remettre à 0 une zone mémoire qui sera utilisée plus tard par quelqu'un d'autre qui, lui, y mettra autre chose ??? T'es-tu embêté à remettre à 0 tes variables "i"," j" et "o" avant de quitter ta fonction ??? Quand tu cherches à comprendre comment fonctionne une chose, n'oublie jamais que derrière cette chose il y a un type comme toi qui l'a programmée...
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    avril 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 18
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : avril 2017
    Messages : 11
    Points : 8
    Points
    8

    Par défaut

    Mais ce que je ne comprends pas avec free, c'est que lorsque je l'utilise juste avant mon return, ma variable devient nulle...

    EDIT : Non en fait elle ne devient pas nulle, c'est juste mon return qui ne fonctionne plus. Je ne comprends pas vraiment pourquoi ?

  8. #8
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    5 706
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 5 706
    Points : 15 602
    Points
    15 602
    Billets dans le blog
    1

    Par défaut

    Citation Envoyé par Deezio Voir le message
    Mais ce que je ne comprends pas avec free, c'est que lorsque je l'utilise juste avant mon return, ma variable devient nulle...
    Ben que tu l'utilises juste après le malloc ou juste avant le return c'est pareil dans les deux cas. Tu libères la zone avant de l'avoir utilisée (parce que si tu la retournes, c'est quand-même un peu pour qu'elle soit utilisée par l'appelant non ???). Et donc dans les deux cas tu l'as allouée et remplie pour rien.

    Citation Envoyé par Deezio Voir le message
    Non en fait elle ne devient pas nulle, c'est juste mon return qui ne fonctionne plus.
    Le return fonctionne très bien. Ou alors les lois du C ont basculé dans le néant.

    Citation Envoyé par Deezio Voir le message
    Je ne comprends pas vraiment pourquoi ?
    Parce que tu n'affiches probablement pas ce qu'il faut. A mon avis tu tentes d'afficher via my_putstr() donc tu tentes d'afficher le contenu de la zone. Mais si tu veux vérifier que ton return a bien fonctionné, c'est la chose retournée qu'il te faut afficher donc ici la valeur numérique de "dest" avant de la renvoyer => printf("%d\n", dest) // Ou printf("%x", dest) si tu préfères l'avoir en hexa.
    Et dans le main tu affiches pareillement la valeur de ce que tu reçois.
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int main(int ac, char **av)
    {
    	char *xxx=sum_params(ac, av);
    	printf("%d\n", xxx);
    	...
    }

    Et tu verras que ce sont les mêmes.

    PS: pourquoi t'as cliqué sur "résolu" ??? La discussion ne l'est pas tout à fait...
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  9. #9
    Futur Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    avril 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 18
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : avril 2017
    Messages : 11
    Points : 8
    Points
    8

    Par défaut

    Citation Envoyé par Sve@r Voir le message
    Ben que tu l'utilises juste après le malloc ou juste avant le return c'est pareil dans les deux cas. Tu libères la zone avant de l'avoir utilisée (parce que si tu la retournes, c'est quand-même un peu pour qu'elle soit utilisée par l'appelant non ???). Et donc dans les deux cas tu l'as allouée et remplie pour rien.
    Mais alors si je ne dois pas utilisé free juste avant le return, quand est-ce que je dois l'utilisé ? Parce qu'une fois sorti de ma fonction, la zone ne peux plus être libéré si ?

    Plus une question, mais qui n'est pas pour ce programme, mais j'en profite sur ce : quand on veut "malloc", une chaine de caractère, on fait malloc(sizeof(char)*nbChar), mais pour un tableau de chaine de caractère, comment faire ? parce que j'ai pensé qu'il fallait faire malloc(sizeof(char)*nbMaxChar*nbCase), sauf que ça ne fonctionne pas il me semble :/. Après je sais que si je malloc chaque case ça marche, mais bon, ça me semble évident qu'il doit y avoir un autre moyen non ?

  10. #10
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    5 706
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 5 706
    Points : 15 602
    Points
    15 602
    Billets dans le blog
    1

    Par défaut

    Citation Envoyé par Deezio Voir le message
    Mais alors si je ne dois pas utilisé free juste avant le return, quand est-ce que je dois l'utilisé ?
    Quand tu ne te sers plus de la zone allouée. Or visiblement tu t'en sers encore dans le main. Donc dans le main.

    Citation Envoyé par Deezio Voir le message
    Parce qu'une fois sorti de ma fonction, la zone ne peux plus être libéré si ?
    Ben si. D'ailleurs c'est la fonction malloc() qui alloue mais quand tu libères tu en es bien sorti de cette fonction malloc() !!! Alors si tu peux libérer hors de malloc() je ne vois pas trop pourquoi tu ne pourrais pas libérer hors de autre chose...

    C'est là la chose principale à comprendre: tu as un énorme tas de mémoire qu'on nomme "le tas" justement et qui est en dehors de toute fonction. malloc va réserver une partie de ce tas et te donner l'adresse de cette partie. Ensuite, une fois que tu as cette adresse tu peux la faire passer de fonction en fonction jusqu'au moment où tu n'en as plus besoin. Et donc là tu passes cette adresse à free qui, lui, va aller faire ce qu'il faut dans le tas.

    Citation Envoyé par Deezio Voir le message
    Plus une question, mais qui n'est pas pour ce programme, mais j'en profite sur ce : quand on veut "malloc", une chaine de caractère, on fait malloc(sizeof(char)*nbChar), mais pour un tableau de chaine de caractère, comment faire ?
    parce que j'ai pensé qu'il fallait faire malloc(sizeof(char)*nbMaxChar*nbCase), sauf que ça ne fonctionne pas il me semble :/
    Ben si, ça fonctionne. malloc() travaille en caractères. Si tu veux allouer des trucs plus gros il te faut multiplier par 1) le nombre de trucs et 2) la taille du truc...
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  11. #11
    Futur Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    avril 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 18
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : avril 2017
    Messages : 11
    Points : 8
    Points
    8

    Par défaut

    Dernière question et après je pense que ça sera plutôt clair, manquera juste de l’entraînement pour éclaircir encore tout ça.
    Si je ne libère pas les zones allouées avec malloc à la fin de mon programme, qu'est-ce qu'il se passe ? Quand je quitte le programme l'ordinateur va-t-il s'occuper de libérer ces zones, ou bien seront-elles allouées jusqu'à la prochaine utilisation du même programme ..?

  12. #12
    Membre émérite
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    décembre 2015
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : décembre 2015
    Messages : 478
    Points : 2 263
    Points
    2 263

    Par défaut

    Heureusement que lors de l'arrêt d'un programme même inopiné, et même s'il est buggué; Toute la mémoire est rendue, tous les threads sont arrêtés et tous les fichiers sont fermés. Si ça restait, ça serait au beau merdier!

  13. #13
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    5 706
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 5 706
    Points : 15 602
    Points
    15 602
    Billets dans le blog
    1

    Par défaut

    Citation Envoyé par dalfab Voir le message
    Si ça restait, ça serait au beau merdier!
    A une certaine époque c'était le cas. Fallait redémarrer l'ordi pour récupérer sa mémoire perdue...

    Citation Envoyé par Deezio Voir le message
    ou bien seront-elles allouées jusqu'à la prochaine utilisation du même programme ..?
    Ca aurait été intéressant comme concept...
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

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

Discussions similaires

  1. Réponses: 12
    Dernier message: 01/09/2014, 16h12
  2. Réponses: 3
    Dernier message: 07/03/2009, 14h44
  3. [XSL] Problème d'echappement dans une chaine de caractère
    Par thierry_b dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 03/03/2009, 09h49
  4. Réponses: 2
    Dernier message: 29/07/2008, 12h23
  5. Réponses: 4
    Dernier message: 10/07/2008, 13h34

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