Existe-t-il une longueur maximale pour un tableau en C ++?
Est-ce une limite C ++ ou dépend-elle de ma machine? Est-ce que c'est modifiable? Cela dépend-il du type de la matrice?
Puis-je briser cette limite d'une manière ou d'une autre ou dois-je rechercher un meilleur moyen de stocker des informations? Et quel devrait être le moyen le plus simple?
Ce que je dois faire est de stocker un long long int sur un tableau, je travaille dans un environnement Linux. Ma question est: que dois-je faire si je dois stocker un tableau de N entiers longs longs avec N> 10 chiffres?
J'en ai besoin parce que j'écris un algorithme cryptographique (comme par exemple le p-Pollard) pour l'école, et que je frappe ce mur d'entiers et de longueur de représentation des tableaux.
new
oumalloc
. Un morceau de mémoire plus grand qu'un tableau est accessible via un pointeur.Personne n'a mentionné la limite de la taille du cadre de la pile .
Il y a deux emplacements de mémoire pouvant être alloués:
La limite de taille ici est une combinaison du matériel disponible et de la capacité du système d'exploitation à simuler de l'espace en utilisant d'autres périphériques pour stocker temporairement les données inutilisées ( c'est-à-dire déplacer les pages sur le disque dur).
La limite de taille ici est définie par le compilateur (avec des limites matérielles possibles). Si vous lisez la documentation du compilateur, vous pouvez souvent modifier cette taille.
Ainsi si vous allouez dynamiquement un tableau (la limite est grande et décrite en détail par d'autres articles.
Sinon, si le tableau est alloué sur la pile, vous êtes limité par la taille du cadre de la pile. NB Les vecteurs et autres conteneurs ont une petite présence dans la pile, mais généralement la majeure partie des données se trouve sur le tas.
la source
new
oumalloc
).Global Arrays
que ce ne soit pas une beauté et qu'il vaut mieux les éviter, ils ne relèvent pas des restrictions dustack
, et vous n'avez pas besoinmalloc
/free
travaillez avec eux.En regardant cela d'un point de vue pratique plutôt que théorique, sur un système Windows 32 bits, la quantité totale maximale de mémoire disponible pour un seul processus est de 2 Go. Vous pouvez briser la limite en passant à un système d'exploitation 64 bits avec beaucoup plus de mémoire physique, mais le fait de le faire ou de rechercher des alternatives dépend beaucoup de vos utilisateurs prévus et de leurs budgets. Vous pouvez également l'étendre quelque peu en utilisant PAE .
Le type de tableau est très important, car l'alignement de la structure par défaut sur de nombreux compilateurs est de 8 octets, ce qui est très inutile si l'utilisation de la mémoire est un problème. Si vous utilisez Visual C ++ pour cibler Windows, consultez la directive #pragma pack pour résoudre ce problème.
Une autre chose à faire est de regarder ce que les techniques de compression de la mémoire pourraient vous aider, comme les matrices éparses, la compression à la volée, etc ... Encore une fois, cela dépend fortement de l'application. Si vous modifiez votre message pour donner plus d'informations sur ce qui se trouve réellement dans vos tableaux, vous obtiendrez peut-être des réponses plus utiles.
Edit: Étant donné un peu plus d'informations sur vos besoins exacts, vos besoins de stockage semblent être compris entre 7,6 Go et 76 Go non compressés, ce qui nécessiterait une boîte de 64 bits assez coûteuse pour stocker en tant que tableau en mémoire en C ++. Cela soulève la question de savoir pourquoi voulez-vous stocker les données en mémoire, là où l'on suppose la vitesse d'accès, et pour permettre un accès aléatoire. La meilleure façon de stocker ces données en dehors d'un tableau dépend en grande partie de la façon dont vous souhaitez y accéder. Si vous devez accéder aux membres du groupe de manière aléatoire, pour la plupart des applications, il existe généralement des moyens de regrouper des groupes de données qui ont tendance à être consultés en même temps. Par exemple, dans les grandes bases de données SIG et spatiales, les données sont souvent regroupées par zone géographique. En termes de programmation C ++, vous pouvez remplacer l'opérateur de tableau [] pour récupérer des parties de vos données à partir du stockage externe si nécessaire.
la source
Je suis d'accord avec ce qui précède, que si vous initialisez votre tableau avec
alors SIZE est limité par la taille d'un entier. Mais vous pouvez toujours malloc une partie de la mémoire et avoir un pointeur vers elle, aussi gros que vous le souhaitez tant que malloc ne renvoie pas NULL.
la source
int oops[INT_MAX]{0};
Il génère,C2148 - total size of array must not exceed 0x7fffffff bytes
66%
mémoire actuellement utilisée avant de lancer mon application en tant que débogage sur Windows 10 avec VS2017, j'ai une limite non définie sur la taille d'un tableau int avec lequel je peux initialiser0
. Parfois, je peux le faire avec ~ 257k éléments, parfois j'obtiens un débordement de pile. Si j'ajoute quelque chose à mon application en plus du principal et du tableau, ce nombre diminue (évidemment). J'ai dû expérimenter pour déterminer ce nombre, donc je ne vois pas comment cette métrique peut être invoquée au-delà de la connaissance de vos limites théoriques dans le vide.Pour résumer les réponses, les étendre et pour répondre directement à votre question:
Non, C ++ n'impose aucune limite pour les dimensions d'un tableau.
Mais comme la matrice doit être stockée quelque part en mémoire, les limites liées à la mémoire imposées par d'autres parties du système informatique s'appliquent. Notez que ces limites ne sont pas directement liées aux dimensions (= nombre d'éléments) du tableau, mais plutôt à sa taille (= quantité de mémoire prise). Dimensions ( D ) et la taille (en mémoire S ) d'un réseau ne sont pas les mêmes, car ils sont liés par la mémoire prise par un seul élément ( E ): S = D * E .
MaintenantE dépend de:
`` espace perdu '' (remplissage) entre les éléments
Notez également que vous obtenez généralement différentes limitations liées à la mémoire en allouant les données du tableau sur la pile (en tant que variable automatique
int t[N]
:), ou sur le tas (allocation dynamique avecmalloc()
/new
ou en utilisant des mécanismes STL), ou dans la partie statique de la mémoire de processus (comme une variable statique:)static int t[N]
. Même lors de l'allocation sur le tas, vous avez toujours besoin d'une petite quantité de mémoire sur la pile pour stocker des références aux blocs de mémoire alloués au tas (mais c'est généralement négligeable).La taille du
size_t
type n'a aucune influence sur le programmeur (je suppose que le programmeur utilise lesize_t
type pour l'indexation, comme il est conçu pour cela), car le fournisseur du compilateur doittypedef
lui donner un type entier suffisamment grand pour adresser la quantité maximale de mémoire possible pour la plate-forme donnée architecture.Les sources des limitations de la taille de la mémoire proviennent de
Ils ne peuvent pas être `` modifiés '' au niveau de l'application, mais vous êtes libre d'utiliser un autre compilateur (pour modifier les limites de taille de la pile), ou portez votre application en 64 bits, ou portez-la sur un autre système d'exploitation, ou modifiez le / configuration de la mémoire virtuelle de la machine (virtuelle? physique?).
Il n'est pas rare (et même conseillé) de traiter tous les facteurs ci-dessus comme des perturbations externes et donc comme des sources possibles d'erreurs d'exécution, et de soigneusement vérifier et réagir aux erreurs liées à l'allocation de mémoire dans le code de votre programme.
Donc enfin: bien que C ++ n'impose aucune limite, vous devez quand même vérifier les conditions défavorables liées à la mémoire lors de l'exécution de votre code ... :-)
la source
Comme l'ont noté de nombreuses excellentes réponses, il existe de nombreuses limites qui dépendent de votre version du compilateur C ++, du système d'exploitation et des caractéristiques de l'ordinateur. Cependant, je suggère le script suivant sur Python qui vérifie la limite sur votre machine.
Il utilise la recherche binaire et à chaque itération vérifie si la taille moyenne est possible en créant un code qui tente de créer un tableau de la taille. Le script essaie de le compiler (désolé, cette partie ne fonctionne que sous Linux) et d'ajuster la recherche binaire en fonction du succès. Vérifiez-le:
Vous pouvez l'enregistrer sur votre machine et la lancer, et elle imprimera la taille maximale que vous pouvez créer. Pour ma machine, c'est 2305843009213693951.
la source
Une chose que je ne pense pas a été mentionnée dans les réponses précédentes.
Je sens toujours une "mauvaise odeur" dans le sens du refactoring lorsque les gens utilisent de telles choses dans leur conception.
C'est un vaste éventail et peut-être pas la meilleure façon de représenter vos données à la fois d'un point de vue d'efficacité et d'un point de vue de performance.
à votre santé,
Rob
la source
Si vous devez gérer des données aussi volumineuses, vous devrez les diviser en blocs gérables. Tout ne rentrera pas dans la mémoire d'un petit ordinateur. Vous pouvez probablement charger une partie des données du disque (ce qui convient raisonnablement), effectuer vos calculs et les modifier, les stocker sur le disque, puis répéter jusqu'à ce que vous ayez terminé.
la source
Aussi ennuyeusement non spécifiques que soient toutes les réponses actuelles, elles ont généralement raison, mais avec de nombreuses mises en garde, pas toujours mentionnées. L'essentiel est que vous avez deux limites supérieures, et une seule d'entre elles est réellement définie, donc YMMV :
1. Délais de compilation
Fondamentalement, ce que votre compilateur autorisera. Pour Visual C ++ 2017 sur une boîte x64 Windows 10, il s'agit de ma limite maximale au moment de la compilation avant d'engager la limite de 2 Go,
Si je faisais ça à la place,
J'aurais:
Je ne sais pas comment 2G corrèle à
255999996
/7
. J'ai recherché sur Google les deux nombres, et la seule chose que j'ai pu trouver qui était peut-être liée était cette * nix Q&A sur un problème de précision avecdc
. Dans tous les cas, le type de tableau int que vous essayez de remplir ne semble pas avoir d'importance, le nombre d'éléments pouvant être alloués.2. Limites d'exécution
Votre pile et votre tas ont leurs propres limites. Ces limites sont à la fois des valeurs qui changent en fonction des ressources système disponibles, ainsi que du «poids» de votre application elle-même. Par exemple, avec mes ressources système actuelles, je peux faire fonctionner ceci:
Mais si je le peaufine un peu ...
Bam! Débordement de pile!
Et juste pour détailler toute la lourdeur de votre point d'application, c'était bon à faire:
Mais cela a provoqué un débordement de pile:
la source
Je suis surpris que la fonction membre max_size () de std :: vector n'ait pas été mentionnée ici.
Nous savons que cela
std::vector
est implémenté comme un tableau dynamique sous le capot, doncmax_size()
devrait donner une approximation très proche de la longueur maximale d'un tableau dynamique sur votre machine.Le programme suivant crée un tableau de la longueur maximale approximative du tableau pour différents types de données.
Sur mon macOS (version 5.0.1 de clang), j'obtiens ce qui suit:
Sur ideone gcc 8.3, j'obtiens:
Il est à noter qu'il s'agit d'une limite théorique et que sur la plupart des ordinateurs, vous manquerez de mémoire bien avant d'atteindre cette limite. Par exemple, nous voyons que pour type
char
ongcc
, le nombre maximum d'éléments est égal au maximum destd::size_t
. En essayant ceci , nous obtenons l'erreur:Enfin, comme le souligne @MartinYork, pour les tableaux statiques, la taille maximale est limitée par la taille de votre pile.
la source
Comme cela a déjà été souligné, la taille du tableau est limitée par votre matériel et votre système d'exploitation (man ulimit). Cependant, votre logiciel ne peut être limité que par votre créativité. Par exemple, pouvez-vous stocker votre «matrice» sur le disque? Avez-vous vraiment besoin de longs longs entiers? Avez-vous vraiment besoin d'un tableau dense? Avez-vous même besoin d'un tableau?
Une solution simple serait d'utiliser Linux 64 bits. Même si vous ne disposez pas physiquement de suffisamment de RAM pour votre matrice, le système d'exploitation vous permettra d'allouer de la mémoire comme si vous le faisiez puisque la mémoire virtuelle disponible pour votre processus est probablement beaucoup plus grande que la mémoire physique. Si vous avez vraiment besoin d'accéder à tout ce qui se trouve dans la matrice, cela revient à le stocker sur disque. En fonction de vos modèles d'accès, il peut y avoir des moyens plus efficaces de le faire (par exemple: utiliser mmap (), ou simplement stocker les données séquentiellement dans un fichier (auquel cas Linux 32 bits suffirait)).
la source
Je contournerais cela en créant un tableau dynamique 2d:
plus à ce sujet ici https://stackoverflow.com/a/936702/3517001
la source