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 :

Taille trop grande pour malloc()


Sujet :

C

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Architecte réseau
    Inscrit en
    Novembre 2016
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte réseau

    Informations forums :
    Inscription : Novembre 2016
    Messages : 11
    Points : 9
    Points
    9
    Par défaut Taille trop grande pour malloc()
    Bonjour tout le monde.

    En C, j'ai besoin de crer un tableau d'unsigned long de 3 milliards de lignes qui nécessiteront donc 24G de RAM.

    Avec la déclaration : unsigned long toto[3*1024*1024*1024*sizeof(unsigned long); Ca plante
    J'ai donc utilisé la déclaration suivante :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    unsigned long *toto;
    toto=(unsigned long *)malloc(3*1024*1024*1024*sizeof(unsigned long));
    mais ça plante aussi.

    Si je me limite à 100 Million, ca passe :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    unsigned long *toto;
    toto=(unsigned long *)malloc(1*100*1024*1024*sizeof(unsigned long));

    La machine possède 64G de RAM et je compile sous Ubuntu avec "g++ -o toto toto.cpp". Comment puis je faire pour créer mon tableau ?

    Christophe D.

  2. #2
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    En C, j'ai besoin de crer un tableau d'unsigned long de 3 Milliard de ligne qui nécissiterons donc 24G de RAM.
    C'est certainement une mauvaise idée. Il ne te faut pas 24 Go de RAM disponibles, mais 24 Go de RAM disponibles et contigües. Il faut aussi savoir qu'il y a une mécanique nommé "memory over commit" qui fait que Linux te dit toujours OK quand tu appelles malloc() mais fait planter le programme quand tu tentes d'y accéder et que finalement il n'y avait pas assez de RAM disponible. Je regarde sur le net en même temps que je répond et ce ne serait peut-être pas si simple : https://www.etalabs.net/overcommit.html

    Tu peux lire cette discussion pour voir comment allouer un tableau aussi énorme http://www.developpez.net/forums/d12...-tableau-char/

    Je pense néanmoins que tu devrais revoir ton algo pour travailler par morceaux et non avec un seul tableau.

  3. #3
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Est-ce qu'un mmap ferait l'affaire ?

    Quel est le problème originel ?

  4. #4
    Membre émérite
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Points : 2 601
    Points
    2 601
    Par défaut
    Citation Envoyé par alexandre.dufoure Voir le message
    Bonjour tout le monde.

    En C, j'ai besoin de crer un tableau d'unsigned long de 3 Milliard de ligne qui nécissiterons donc 24G de RAM.
    Bonjour,
    donc en gros du 8 octets par ligne.

    Citation Envoyé par alexandre.dufoure Voir le message
    Avec la déclaration : unsigned long toto[3*1024*1024*1024*sizeof(unsigned long); Ca plante
    Quelle est la taille d'un long sur ton architecture ? Si tu ne sais pas alors pour info si tu compiles en mac/linux 64 bits c'est 8 octets, les autres (win32/64 et mac/linux32) c'est 4 octets. Je vais donc supposer que tu compiles pour mac/linux 64 bits.
    Attention, une déclaration de toto en locale explosera de toute façon ta pile.
    Citation Envoyé par alexandre.dufoure Voir le message

    J'ai donc utilisé la déclaration suivante :

    unsigned long *toto;
    toto=(unsigned long *)malloc(3*1024*1024*1024*sizeof(unsigned long)); mais ça plante aussi.

    Si je me limite à 100 Million, ca passe :
    unsigned long *toto;
    toto=(unsigned long *)malloc(1*100*1024*1024*sizeof(unsigned long));
    Es-tu certain de compiler en 64bits ? Si tu compiles en 32 bits c'est un comportement normal. Ne castes pas les retour de malloc.

    Citation Envoyé par alexandre.dufoure Voir le message

    La machine possède 64G de RAM et je compile sous Ubunutu avec "g++ -o toto toto.cpp". Comment puis je faire pour créer mon tableau ?

    Christophe D.
    Ah ben tu utilises g++, c'est un compilateur c++, donc limite tu es sur le mauvais forum. Utilise gcc pour compiler du C, et du coup de caste plus tes malloc.

    La question → pour quelle architecture compiles-tu ? Attention, je ne te demande pas la plateforme que tu utilises, mais bien si tu compiles en 32 bits ou 64 bits.

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Architecte réseau
    Inscrit en
    Novembre 2016
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte réseau

    Informations forums :
    Inscription : Novembre 2016
    Messages : 11
    Points : 9
    Points
    9
    Par défaut
    Merci pour toutes ces infos qui me permette déjà de progresser et continuer à chercher.

    Pour la compilation, j'utilise gcc aussi et c'est problématique aussi. Pour 32 ou 64 bits, en fait, je ne sais pas. Comment puis savoir et comment passer en 64 bits ?

    Je suis sous Ubuntu en mode console. uname -a me donne : x86_64 x86_64 x86_64 GNU/Linux. Et j'execute sur la même machine et même environement que la compilation.

    P.S. : Merci des infos, ça m'aide pour d'autre chose. Par exemple, cela me met la piste sur un autre phénomène de déclaration de structure dont lizeof ne correspond pas à ce que j'attendais. J'ai donc du utilisé #pragma pack(2) et en plus spécifier la taille manuellement pour chaque variable genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    struct toto
    {
    unsigned long		titi:32;

  6. #6
    Membre émérite
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Points : 2 601
    Points
    2 601
    Par défaut
    Citation Envoyé par alexandre.dufoure Voir le message
    Merci pour toutes ces infos qui me permette déjà de progresser et continuer à chercher.

    Pour la compilation, j'utilise gcc aussi et c'est problématique aussi. Pour 32 ou 64 bits, en fait, je ne sais pas. Comment puis savoir et comment passer en 64 bits ?

    Je suis sous Ubuntu en mode console. uname -a me donne : x86_64 x86_64 x86_64 GNU/Linux. Et j'execute sur la même machine et même environement que la compilation.
    Si tu es sur un linux64 tu devrais avoir un gcc qui compile par défaut pour cette cible. Pour t'en assurer crée un exécutable sans préciser d'options particulières et fait un file sur le fichier. Par exemple en quick and dirty sur la ligne de commande :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $ gcc -o test -xc - << EOF
    int main(void) { return 0; }
    EOF
     
    $ file test
    test: ELF 64-bit LSB executable, x86-64, … <- cette sortie si tu compiles en mode 64 bits
    test: ELF 32-bit LSB executable, Intel 80386, … <- cette sortie si tu compiles en mode 32 bits
    test: ELF 32-bit LSB executable, x86-64,… <- cette sortie si tu compiles en mode 32 bits étendu
    Citation Envoyé par alexandre.dufoure Voir le message
    P.S. : Merci des infos, ça m'aide pour d'autre chose. Par exemple, cela me met la piste sur un autre phénomène de déclaration de structure dont lizeof ne correspond pas à ce que j'attendais. J'ai donc du utilisé #pragma pack(2) et en plus spécifier la taille manuellement pour chaque variable genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    struct toto
    {
    unsigned long		titi:32;
    Là je dis mauvais choix !
    Si tu veux des types entiers de longueur fixe il faut utiliser stdint et uint32_t (par exemple) pour un entier non signé de 32 bits.

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Architecte réseau
    Inscrit en
    Novembre 2016
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte réseau

    Informations forums :
    Inscription : Novembre 2016
    Messages : 11
    Points : 9
    Points
    9
    Par défaut
    Et bien j'ai :

    test: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux

    J'ai essayé de compilé via gcc qui est plus parlant comme vous me le disiez en refusant la compilation du Malloc.

    Si dans le code je met :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    unsigned long *toto;
    toto=(unsigned long *)malloc(1*100*1024*1024*sizeof(unsigned long));
    Ca compile bien et s'execute bien

    Par contre, si dans le code je met :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    unsigned long *toto;
    toto=(unsigned long *)malloc(3*1024*1024*1024*sizeof(unsigned long));
    Ca ne compile pas avec l'erreur : attention : débordement d'entier dans l'expression [-Woverflow]
    Et poutant, je suis donc bien en 64 bits.

  8. #8
    Membre émérite
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Points : 2 601
    Points
    2 601
    Par défaut
    Citation Envoyé par alexandre.dufoure Voir le message
    Et bien j'ai :

    test: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux

    J'ai essayé de compilé via gcc qui est plus parlant comme vous me le disiez en refusant la compilation du Malloc.
    ok, donc tu compiles en ciblant une architecture 64 bits. Utilise gcc pour compiler du C, pas g++ … C et C++ sont deux langages différents.

    Citation Envoyé par alexandre.dufoure Voir le message
    Si dans le code je met :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    unsigned long *toto;
    toto=(unsigned long *)malloc(1*100*1024*1024*sizeof(unsigned long));
    Ca compile bien et s'execute bien

    Par contre, si dans le code je met :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    unsigned long *toto;
    toto=(unsigned long *)malloc(3*1024*1024*1024*sizeof(unsigned long));
    Ca ne compile pas avec l'erreur : attention : débordement d'entier dans l'expression [-Woverflow]
    Et poutant, je suis donc bien en 64 bits.
    Ok, là l'erreur est claire
    En fait c'est tout simple et ne concerne que le compilateur. Quand tu écris une constante le compilateur va essayer de la typer. Si tu ne lui en donnes pas il commence par essayer int, si elle est trop grande pour int il essayera ensuite long, …
    Ici 3 rentre dans un int, donc cette constante sera typée int. Les calculs seront ensuite fait en int et le compilateur connaissant au moment de la compilation toutes les valeurs il va simplifier tout ça. Malheureusement le résultat final ne rentre pas dans un int, d'où le message d'erreur.
    Il y a deux solutions.
    La première consiste à type la constante 3 en unsigned long long grâce au suffixe ULL :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned long *toto=malloc(3ULL*1024*1024*1024*sizeof(unsigned long));
    La première opérande étant maintenant un unsigned long long tout devrait bien se passer. Une solution équivalente est d'utiliser un cast, elle sera plus élégante car plus portable → on utilise le type size_t :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned long *toto=malloc((size_t)3*1024*1024*1024*sizeof(unsigned long));
    dernière solution : on commence par le sizeof car cet opérateur renvoie un entier de type sizeof qui force le type utilisé pour les calculs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned long *toto=malloc(sizeof(unsigned long)*3*1024*1024*1024);
    Et, on ne caste pas les malloc en C.

  9. #9
    Futur Membre du Club
    Homme Profil pro
    Architecte réseau
    Inscrit en
    Novembre 2016
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte réseau

    Informations forums :
    Inscription : Novembre 2016
    Messages : 11
    Points : 9
    Points
    9
    Par défaut
    Ca fonctionne bien merci beaucoup pour la solution et pour tous les autres conseils qui me permette d'avançer.

  10. #10
    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
    C'est très bizarre, parce qu'à ma connaissance, Linux utilise le modèle 64 bits LP64, ce qui signifie que les long sont censés faire 64 bits également...

    À ta place, j'utiliserais un uint64_t (déclaré dans <stdint.h>) pour calculer la taille, puis le mettre dans un size_t sans cast: Ainsi, un compilateur bien configuré te donnera un warning si tu compiles en 32 bits...
    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.

  11. #11
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Points : 7 842
    Points
    7 842
    Par défaut
    Citation Envoyé par alexandre.dufoure
    j'ai besoin de créer un tableau d'unsigned long de 3 Milliard de ligne qui nécessiteront donc 24G de RAM.
    Probablement pas, tout dépend de la taille de ton swap et du taux de remplissage et de la répartition des données dans ce tableau.

    Citation Envoyé par Bktero Voir le message
    C'est certainement une mauvaise idée. Il ne te faut pas 24 Go de RAM disponibles, mais 24 Go de RAM disponibles et contigües.
    Je ne suis pas vraiment d'accord et d'ailleurs, on a déjà eu une discussion là dessus il y a quatre ans vers laquelle tu as donné un lien plus haut.

    Quand on fait un malloc, tout ce qui est fait c'est demander un espace de mémoire virtuelle , pas physique, qui sera accessible à l'adresse retournée. Le système peut réserver cette mémoire tout de suite, ou ne le faire que plus tard, ou jamais, suivant l'OS et la façon dont il est configuré.
    Il n'est pas encore question de mémoire physique.
    Ces 24 Go de mémoire virtuelle ne devront être présents en mémoire physique que dans la mesure où ils seront accédés en lecture ou en écriture. Même dans ce cas, il n'est pas du tout nécessaire que les 24 Go soient contigus, les pages mémoires physique peuvent être placées à n'importe quelles adresses. Il y a un mapping entre adresses logiques (virtuelles) vu du processus et adresses physiques, vers le barrettes de RAM.

    Conclusion, au moment où on fait un malloc de 24 Go, on a besoin de 0 Go de RAM et entre 0 et 24 Go de mémoire virtuelle disponible (c'est à dire somme de la RAM disponible + swap disponible) suivant la configuration. Ensuite, on va consommer de la RAM en fonction de l'utilisation du tableau mais en aucun cas il n'est nécessaire que la mémoire physique soit contiguë.
    ɹǝsn *sıɹɐlos*

  12. #12
    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
    Il faut quand même 24Go libres contigus dans le plan mémoire du processus (mais en 64 bits, ça ne devrait pas être trop problématique)
    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.

  13. #13
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    @jlliagre pour être honnête j'ai relu la discussion après avoir écrit cette phrase... Ne codant que sur des systèmes sans adressage virtuel, j'ai pas pensé à ça. Merci d'avoir relevé cette erreur.

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 24/10/2007, 17h34
  2. Contenu trop grand pour son conteneur
    Par mLk92 dans le forum Mise en page CSS
    Réponses: 3
    Dernier message: 03/10/2007, 22h14
  3. Réponses: 2
    Dernier message: 09/10/2006, 17h36
  4. mon arrière plan trop grand pour le bloc
    Par 123quatre dans le forum Mise en page CSS
    Réponses: 3
    Dernier message: 07/10/2006, 00h54

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