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 :

Limitation allocation memoire malloc


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 60
    Points : 47
    Points
    47
    Par défaut Limitation allocation memoire malloc
    Bonjour,

    J'ai procédé à une allocation mémoire avec la fonction malloc qui me retourne un pointeur nul lorsque je demande plus de 80-85 Mo !! A la base, il m'en faudrait plutôt 500 Mo pour faire un tampon. Je suis sous Windows 7, 64 bits, 4 Go de RAM. J'ai regardé les performances dans le gestionnaire des taches : il utilise 2,6 Go, il en reste environ 1,3 Go de disponible. J'utilise visual studio 2008 express.

    Je ne vois pas ce qui m'empêche d'atteindre les 500 Mo d'allocation mémoire...!?

    Je vais tenter demain la manipulation sur mon PC perso sous windows 10 sous 8Go pour voir comment ça réagit...mais dans tous les cas, je ne comprends pas ce qui limite. D'après les recherches que j'ai vu, je devrais pouvoir dépasser les 530 Mo dont j'ai besoin...!? Un paramètre dans Windows à modifier ou dans Visual C !?

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 897
    Points : 219 633
    Points
    219 633
    Billets dans le blog
    125
    Par défaut
    Bonjour,

    Cela me semble étonnant. Après, si c'est du Windows only, il y a des fonctions d'allocations spécifiques à la WinAPI. Autrement, montrez nous votre code, possible qu'il y ait une erreur.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 60
    Points : 47
    Points
    47
    Par défaut
    Bonjour,

    Ah ok, je ne savais pas qu'il y en avait aussi dans la winAPI. Oui, c'est du windows. J'utilise déjà les threads et la création/écriture de fichiers binaires avec la winAPI, donc je ne suis pas à une de plus ou de moins !

    Je suis exceptionnellement en télétravail aujourd'hui, je ne retrouve pas mon PC de boulot avant Lundi, donc je ne peux pas tester sur le système.

    Si cela semble étonnant, c'est que ça doit venir du code, je dois me tromper sur les types. Pour information, c'est pour une application dans le domaine de l'électronique.

    Voilà la ligne d'allocation du code en question :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    RawMemstartPtr[i] = (ViInt8*)malloc((sizeof(ViInt8)*FetchBlockSize*channelCount[i]*BufferSize)+(4096*channelCount[i]));
     
    if(RawMemstartPtr[i]==NULL)
    {
    	errorCodeStreaming = -1;
    }
    C'est pour faire un tampon de datas comprenant 8 éléments (BufferSize) avec un pointeur read et write qui agiront dessus...!

    La taille de chaque élément fait 32 768 000 octets (FetchBlockSize). Je l'ai défini par rapport au hardware (vu dans la doc constructeur) pour optimiser la vitesse des données. C'est avec cette taille de paquet que j'ai la vitesse max (730M/s). Il y a deux voies de mesures donc channelCount vaut 2 dans le pire des cas.

    Donc pour résumer :

    FetchBlockSize = 32 768 000
    channelCount = 2
    BufferSize = 8
    sizeof(ViInt8) retourne 1

    Ce qui fait 524 296 192 octets à allouer ! Je n'arrive pas à faire mieux que 80-85Mo (ça fonctionne quand je mets BufferSize à 1 au lieu de 8...! Au dessus de cette valeur, il me retourne le code erreur -1 qui indique que le pointeur est nul.

    Le problème vient peut être des types

    FetchBlockSize : ViInt32
    channelCount : ViInt32
    BufferSize : ViInt32

    Ce sont des types particuliers défini par un driver. Quand je regarde le contenu des typedef, ça donne :

    ViInt32 : signed int
    ViInt8 : signed char

    Les données sont en format ViInt8 (défini par le constructeur), donc je n'ai pas le choix du format vu que j'utilise leur library. ViInt8 correspond à un octet donc sizeof(ViInt8) retourne 1 sur mon système.

    Etant donné qu'il y a 3 cartes, ceci est dans une boucle for pour créer N tampons avec N le nombre de cartes utilisées. Mais je ne travaille avec une pour le moment donc on va dire que l'indice i est toujours à 0 pour le moment.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 60
    Points : 47
    Points
    47
    Par défaut
    Je me rends compte en rédigeant le message précédant qu'avec 3 cartes, ça fait 3 malloc de plus de 500 Mo, soit 1,5 Go d'alloué cumulé !!! ça ne passera pas sur le PC avec la RAM installée même si j'arrive à faire le malloc pour une carte. Le client m'a proposé de me donner un PC sous windows 10 avec 32 Go de RAM. Je pense que je vais tout basculer dessus même si ça va être la galère pour réinstaller toutes les applications, drivers et autres...! Mais je vais quand même essayer de comprendre pourquoi ça ne passe pas pour une carte.

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 : 12 721
    Points : 31 044
    Points
    31 044
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Pour vérifier si ça vient du programme ou bien de windows, il faut essayer avec un code minimal. Ex char *pt=malloc(500 * 1024 * 1024) pour allouer 500Mo (oui, je sais, ces cons du bipm ont définitivement tranchés que même en informatique un kilo c'était 1000 et pas 1024, ce qui permet aux voleursvendeurs de dd de nous vendre des disques ne contenant que 97% de la capacité indiquée en toute impunité mais cela ne change rien à l'exemple).
    Ensuite tu montes (il te faut 3 fois cette taille tu crées 3 pointeurs, ou bien un pointeur que tu alloues à 3 fois plus grand). Et tu regardes quand ça plante (à mon avis c'est plus du côté programme et API que du côté OS, d'autant plus qu'il n'y a pas que la RAM qui compte, le swap aussi existe).

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    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 381
    Points : 41 582
    Points
    41 582
    Par défaut
    Vérifie aussi que tu compiles bien en 64 bits, sinon ton processus sera limité à 2Go de mémoire.

  7. #7
    Membre chevronné
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 548
    Points : 1 753
    Points
    1 753
    Par défaut
    Bonsoir,

    Citation Envoyé par soccersoft Voir le message
    Bonjour,

    J'ai procédé à une allocation mémoire avec la fonction malloc qui me retourne un pointeur nul lorsque je demande plus de 80-85 Mo !! A la base, il m'en faudrait plutôt 500 Mo pour faire un tampon. Je suis sous Windows 7, 64 bits, 4 Go de RAM. J'ai regardé les performances dans le gestionnaire des taches : il utilise 2,6 Go, il en reste environ 1,3 Go de disponible. J'utilise visual studio 2008 express.

    Je ne vois pas ce qui m'empêche d'atteindre les 500 Mo d'allocation mémoire...!?

    Je vais tenter demain la manipulation sur mon PC perso sous windows 10 sous 8Go pour voir comment ça réagit...mais dans tous les cas, je ne comprends pas ce qui limite. D'après les recherches que j'ai vu, je devrais pouvoir dépasser les 530 Mo dont j'ai besoin...!? Un paramètre dans Windows à modifier ou dans Visual C !?

    C'est tout à fait normal que vos différentes allocations mémoire échouent et pour le comprendre, il faut d'abord comprendre que l'implémentation et la stratégie d'allocation mémoire avec la fonction malloc ou les fonctions d’allocation d’une API propre au système d'exploitation sont différentes et ce d'un système d'exploitation à un autre.

    Quand bien même après l’allocation mémoire, vous n’obtenez pas de la mémoire réelle de façon immédiate, car les systèmes d'exploitation mettent à disposition des applications qui s'exécutent ; une mémoire virtuelle, dans laquelle le contexte d'exécution de l'application (processus) reçoit une plage de mémoire, mais cette mémoire ne correspond pas directement à celle de la RAM physique (mémoire physique).

    Ainsi pour le cas de malloc, ce dernier n’échoue presque jamais, et même si une allocation semble réussie ( pas de renvoi de nul par la fonction), elle peut conduire à un avortement du processus lorsque l’on tentera d’obtenir réellement la mémoire.


    Exemple: Sur un système d'exploitation GNU/Linux, la fonction d'allocation dynamique malloc permet d'allouer d’autant plus de mémoire que votre ordinateur en possède réellement et n'échoue que dans des cas bien spécifiques ;

    C'est-à-dire qu'il renvoie NULL, soit parce que la taille mémoire sollicitée vaut/est égale à zéro (nulle) ou que la taille mémoire sollicitée ne permet pas de faire une allocation mémoire à cause de l'espace d'adresse du contexte d'exécution de l'application (processus) qui est saturé. En des termes plus précis, cela veut dire plus d'adresse virtuelle (mémoire virtuelle) de disponible.

    Le système d'exploitation peut également refuser l'allocation due aux raisons précédentes et aussi, si la taille sollicitée en une fois n'excède pas la somme de la mémoire physique et du swap.

    Dans les faits, vous avez donc, grâce aux adresses virtuelles, la possibilité d'allouer plus de mémoire que votre ordinateur en dispose et sans pour autant que l'allocation mémoire échoue. Cette illusion est due à un mécanisme connu sous le nom “overcommit-memory” qui considère qu'une application (Cas de GNU/Linux ; BSD) a toujours besoin de plus de mémoire qu'il en a réellement besoin et de ce fait, toute allocation mémoire ne devrait jamais échouer sauf dans les circonstances énoncées précédemment.

    Quant à la mémoire réelle sous GNU/Linux, elle vous est attribuée au moment de l'écriture des données aux emplacements des adresses mémoire en question et pas avant grâce à l'unité de gestion mémoire alias MMU ou PMMU (pour paged memory management unit) qui a la lourde tâche de déclencher un mécanisme qui permet d'obtenir réellement de la mémoire.

    Le MMU va effectuer tout le boulot de transformation des adresses virtuelles en une adresse physique ; et si les données écrites tentent de dépasser les limites de ressource réelles du système, c'est-à-dire l’occupation totale de la mémoire plus le swap comme évoqué précédemment ; ne permettant plus au système d'exploitation d’allouer de la mémoire à un autre processus (ou pour la stabilité du système). Ce dernier (le système d’exploitation) va déclencher un mécanisme de sûreté OMM-Killer (pour out of Memory Killer) qui va mettre fin au processus gourmand et libérer l’ensemble des ressources attribuées évitant que le système se frise ou plante totalement.

    Et à ma connaissance, aucun système d'exploitation sur PC n'échappe à cette règle, et encore une fois, tout dépend de la quantité de mémoire sollicitée et de la stratégie d'allocation qu'utilise la fonction malloc pour pouvoir réserver de la mémoire souhaitée et en disposer ; tout comme cela dépend également de l'implémentation de la fonction qui varie d'un système à un autre.

    Quant au système d'exploitation Windows, il permettra un overcommit-memory (plus de mémoire virtuelle que votre ordinateur n’en dispose) si et seulement si vous disposez d'espace libre sur votre disque dur pour temporairement sauvegarder les adresses mémoires virtuelles sollicitées par votre application. Il va donc créer un semblant de swap pour vous permettre d'avoir ce qu'il vous faut et ne pas mettre en péril la stabilité du système d'exploitation. Cas contraire, l'allocation mémoire échouera faute de ressources (mémoire disponible). Et si vraiment vous souhaiter avoir les 512 Mo va falloir procéder autrement avec d’autres fonctions qui permettent de solliciter pour votre processus plus de mémoire.

    En utilisant les fonctions comme « SetProcessWorkingSetSize » pour obtenir plus de plages de l’espace d’adresse virtuel ; mais toutefois, cela peut potentiellement dégrader les performances du système et forcer le système mettre fin au processus. Cependant en verrouillant cet espace allouer avec "VirtualLock" le système n'a pas d’autres choix de réserver cette zone mémoire, mais là aussi au risque de manquer de ressources ou dégrader les performances sans compter que cette approche pourrait bien siphonner les ressources des autres processus, mais a vérifier.


    Au final malloc, ne réserve que des quantités d’espace d’adresse dans l'espace d'adresse virtuelle de votre processus en indiquant au système d’exploitation via des sous-routines la quantité d’adresse qu’il souhaite et si l’allocation semble réussie, elle peut tout de même conduire à un avortement du processus lorsque l’on tentera d’obtenir réellement la mémoire.Et sollicité une quantité de mémoire supérieur à la totalité de la mémoire physique en une seule fois; vous sera niet.
    Opté pour une projection mémoire ou dégradation des ressources volontaire, mais en sachant ce que vous faites, et même sous une machine 64 bit rien ne vous dit que les performances seront au beau fixe.


    À bientôt.

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 60
    Points : 47
    Points
    47
    Par défaut
    Bonjour à vous,

    Merci pour les informations. J'ai fini par résoudre mon problème et c'était plus ou moins ce que vous disiez. En fait, je n'avais pas tout dit. Ce programme en C était en fait une DLL que j'appelais depuis Scilab. Il semblerait que ça soit Scilab qui me limitait. J'ai fait un test pour m'en rendre compte, j'ai compilé le code en 32 bits sous visual c non plus en DLL mais pour avoir un executable, c'est à dire sans passer par scilab, et ça a marché. ça marche quand je lance le .exe, il fait bien l'allocation des 500Mo et ça ne marche pas quand je lance la DLL depuis scilab.

    La version 5 de scilab dispose d'une pile limitée en taille qui gère la mémoire. En installant Scilab 64 bits au lieu de Scilab 32 bits, l'allocation a fonctionné, j'ai du au passage compiler la DLL en 64 bits pour que Scilab 64 bits l'accepte. Le fait de passer en Scilab 64 bits multiplie la taille max de la pile par 3 chez moi.

    Par contre, ce que je comprends moins bien, c'est que j'ai procédé à 3 allocations et les adresses retournées me paraissent suspectes....
    SizeMemory=524296192 (taille allouées pour chaque allocation)

    Les 3 pointeurs retournés par malloc :

    ptrMemory1=458227824
    ptrMemory2=982581360
    ptrMemory3=112

    Je ne comprends pas qu'ils me donnent l'adresse 112 pour le pointeur 3 alors que l'adresse 1 est 458227824 avec 524296192 octets de réservés.....est ce que l'adresse 3 n'empiètent pas sur les données du pointeur 1 !? A moins que ça fonctionne par pages et que ces valeurs adresses soient indépendantes !? Je ne sais pas si les valeurs retournées sont des valeurs absolues ou relatives...! Je vais essayer de trouver des infos sur la structure des allocations mémoires pour voir si ces pointeurs retournés sont cohérents.

    il me vient aussi l'idée à l'instant de faire un test....je vais essayer de remplir les données des pointeurs et lire les données, je verrai bien si y a empiétements ou non....possible aussi que j'ai un type mal adapté...à moins que ça soit la pile scilab qui gère ses propres adresses...je vais aussi lancer ce programme en mode .exe indépendamment de scilab pour voir ce qu'il me retourne en adresses...


    Voilà le code test pour les plus curieux

    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
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    unsigned int SizeMemory;	
    	int errorCodeStreaming1 = 0;
    	int errorCodeStreaming2 = 0;
    	int errorCodeStreaming3 = 0;
    	unsigned int channelCount = 2;
    	unsigned int FetchBlockSize = 32768000;
    	unsigned int BufferSize = 8;
    	unsigned long *ptrMemory1;
    	unsigned long *ptrMemory2;
    	unsigned long *ptrMemory3;
     
    	char conv[16];
    	char FilenameDebug[100];
    	char test[16];
     
    	strcpy_s(FilenameDebug,100,"E:\\Debug.ini");
     
    	SizeMemory = (1*FetchBlockSize*channelCount*BufferSize)+(4096*channelCount);
    	ptrMemory1 = (unsigned long *)malloc(SizeMemory);
    	ptrMemory2 = (unsigned long *)malloc(SizeMemory);
    	ptrMemory3 = (unsigned long *)malloc(SizeMemory);
     
    	if(ptrMemory1==NULL)
    	{
    		errorCodeStreaming1 = -1;
    	}
     
    	if(ptrMemory2==NULL)
    	{
    		errorCodeStreaming2 = -1;
    	}
     
    	if(ptrMemory3==NULL)
    	{
    		errorCodeStreaming3 = -1;
    	}
     
    	_itoa_s(errorCodeStreaming1, conv, 10);
    	WritePrivateProfileStringA((LPCSTR)"Debug","errorCodeStreaming1",conv,(LPCSTR)FilenameDebug);
     
    	_itoa_s(errorCodeStreaming2, conv, 10);
    	WritePrivateProfileStringA((LPCSTR)"Debug","errorCodeStreaming2",conv,(LPCSTR)FilenameDebug);
     
    	_itoa_s(errorCodeStreaming3, conv, 10);
    	WritePrivateProfileStringA((LPCSTR)"Debug","errorCodeStreaming3",conv,(LPCSTR)FilenameDebug);
     
    	_itoa_s(SizeMemory, conv, 10);
    	WritePrivateProfileStringA((LPCSTR)"Debug","SizeMemory",conv,(LPCSTR)FilenameDebug);
     
    	_itoa_s(unsigned long(ptrMemory1), conv, 10);
    	WritePrivateProfileStringA((LPCSTR)"Debug","ptrMemory1",conv,(LPCSTR)FilenameDebug);
     
    	_itoa_s(unsigned long(ptrMemory2), conv, 10);
    	WritePrivateProfileStringA((LPCSTR)"Debug","ptrMemory2",conv,(LPCSTR)FilenameDebug);
     
    	_itoa_s(unsigned long(ptrMemory3), conv, 10);
    	WritePrivateProfileStringA((LPCSTR)"Debug","ptrMemory3",conv,(LPCSTR)FilenameDebug);
     
     
    	free(ptrMemory1);
    	free(ptrMemory2);
    	free(ptrMemory3);

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 60
    Points : 47
    Points
    47
    Par défaut
    Je viens de faire le test sans passer par scilab de ce code et le résultat est différent, ça me retourne ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    errorCodeStreaming1=0
    errorCodeStreaming2=0
    errorCodeStreaming3=0
    SizeMemory=524296192
    ptrMemory1=8454208
    ptrMemory2=532807744
    ptrMemory3=1057161280

    ça me parait bien plus cohérent ! C'est bien scilab qui m'affecte des valeurs d'adresses surement avec sa gestion mémoire de la pile....reste à savoir si c'est normal ou si c'est planté car les adresses sont bizarres...j'atteins peut être le max de sa pile !

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 60
    Points : 47
    Points
    47
    Par défaut
    J'ai rempli toute l'allocation mémoire 1 de 1, l'allocation 2 de 2 et la 3 de 3 et il s'avère qu'en regardant toutes les cases, tout semble ok, les données sont bonnes, il n'y a pas d'écrasement. Je ne comprends pas l'adressage mémoire avec ces adresses bizarres, mais si ça fonctionne...

  11. #11
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    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 381
    Points : 41 582
    Points
    41 582
    Par défaut
    Ce sont tes appels à _itoa_s qui sont inadaptés: Si tu castes un pointeur 64 bits en unsigned long, sous Windows (qui utilise le modèle LLP64); tu perdras les 32 bits supérieurs!
    Il te faut une fonction capable de convertir un long long en chaîne de caractères... Par exemple, snprintf() (sans underscore) sur un Visual Studio assez récent pour le supporter.

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

Discussions similaires

  1. Allocation memoire limite & valeurs
    Par Lolitaaa dans le forum Général Java
    Réponses: 2
    Dernier message: 26/11/2010, 11h59
  2. limite de l'allocation memoire?
    Par yan dans le forum MFC
    Réponses: 8
    Dernier message: 29/12/2005, 11h53
  3. [Perf][JVM] limite de memoire ?
    Par xlurp dans le forum Général Java
    Réponses: 6
    Dernier message: 01/11/2004, 11h52
  4. Réponses: 13
    Dernier message: 05/01/2004, 19h00
  5. Allocation memoire Limité avec TurboC
    Par sebastien51 dans le forum Autres éditeurs
    Réponses: 3
    Dernier message: 15/10/2003, 23h32

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