OVH Cloud OVH Cloud

Allocation tableau -> seg Fault

7 réponses
Avatar
Fanny Chevalier
Bonjour,

Je voudrais comprendre pourquoi une allocation d'un tableau (su'il soit
a une dimension ou deux) provoque une faute de segmentation dès que je
dépasse une certaine taille (pas réellement astronomique a vrai dire)...

Voici le code qui bugge :
// sur machine1 : 1400 ok, 1500 erreur segmentation
// si on commente la ligne gris[5]=6;, OK tout le temps...

// sur machine2 : 1600 ok, 1700 erreur segmentation
// si on commente la ligne gris[5]=6;, OK tout le temps...

const int MAXI = 1600;

int main()
{
int gris[MAXI*MAXI]; // c'est pareil avec [MAXI][MAXI]
gris[5]=6;
return 1;
}

Quelqu'un aurait-il une piste ?

Merci par avance,
Fanny

7 réponses

Avatar
Marc Boyer
In article <crger4$sr5$, Fanny Chevalier wrote:
Je voudrais comprendre pourquoi une allocation d'un tableau (su'il soit
a une dimension ou deux) provoque une faute de segmentation dès que je
dépasse une certaine taille (pas réellement astronomique a vrai dire)...

Voici le code qui bugge :
// sur machine1 : 1400 ok, 1500 erreur segmentation
// si on commente la ligne gris[5]=6;, OK tout le temps...

// sur machine2 : 1600 ok, 1700 erreur segmentation
// si on commente la ligne gris[5]=6;, OK tout le temps...

const int MAXI = 1600;

int main()
{
int gris[MAXI*MAXI]; // c'est pareil avec [MAXI][MAXI]


Tu crées un tableau de 2560000 int, soit, en supposant des int à 4
octets, environ 10Mo.
Sans être énorme, en effet, ton OS peut être configuré pour refuser
d'allouer 10Mo dans l'espace d'allocation des variables automatiques
(souvent la pile).

Quelqu'un aurait-il une piste ?


Modifier un paramêtre de l'OS, ou tenter une allocation dynamique
(souvent moins limitée).

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.

Avatar
James Kanze
Marc Boyer wrote:
In article <crger4$sr5$, Fanny Chevalier
wrote:


Je voudrais comprendre pourquoi une allocation d'un tableau
(su'il soit a une dimension ou deux) provoque une faute de
segmentation dès que je dépasse une certaine taille (pas
réellement astronomique a vrai dire)...



Voici le code qui bugge :
// sur machine1 : 1400 ok, 1500 erreur segmentation
// si on commente la ligne gris[5]=6;, OK tout le temps...



// sur machine2 : 1600 ok, 1700 erreur segmentation
// si on commente la ligne gris[5]=6;, OK tout le temps...



const int MAXI = 1600;



int main()
{
int gris[MAXI*MAXI]; // c'est pareil avec [MAXI][MAXI]



Tu crées un tableau de 2560000 int, soit, en supposant des int à 4
octets, environ 10Mo.
Sans être énorme, en effet, ton OS peut être configuré pour refuser
d'allouer 10Mo dans l'espace d'allocation des variables automatiques
(souvent la pile).


J'entends ça souvent dernièrement. Quels sont ces OS ? Je ne
l'ai pas essayé récemment, mais j'ai déjà alloué des tableaux de
plus d'un Go sous Solaris (sur Sparc). (Je sais que HP/UX avait
des limites assez bas, mais il n'y a pas de raison sur un Sparc
ou un Intel de ne pas permettre pratiquement tout l'espace
adressable dans un processus mono-thread.)

--
James Kanze home: www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34


Avatar
Arnaud Debaene
James Kanze wrote:

J'entends ça souvent dernièrement. Quels sont ces OS ? Je ne
l'ai pas essayé récemment, mais j'ai déjà alloué des tableaux de
plus d'un Go sous Solaris (sur Sparc). (Je sais que HP/UX avait
des limites assez bas, mais il n'y a pas de raison sur un Sparc
ou un Intel de ne pas permettre pratiquement tout l'espace
adressable dans un processus mono-thread.)
Sous Windows : la taille maximale de la pile est fixée à l'édition de lien

pour le thread principal, et par programmation lors du démarrage des threads
secondaires. Avec les outils courants, la valeur par défaut est de 1 MO pour
la pile du thread principal.

Je pense que sur les processeur Intel, c'est lié à la pile qui grossit "vers
le bas".

Arnaud

Avatar
Jean-Marc Bourguet
James Kanze writes:

Marc Boyer wrote:
In article <crger4$sr5$, Fanny Chevalier
wrote:

Je voudrais comprendre pourquoi une allocation d'un tableau
(su'il soit a une dimension ou deux) provoque une faute de
segmentation dès que je dépasse une certaine taille (pas
réellement astronomique a vrai dire)...

Voici le code qui bugge :
// sur machine1 : 1400 ok, 1500 erreur segmentation
// si on commente la ligne gris[5]=6;, OK tout le temps...

// sur machine2 : 1600 ok, 1700 erreur segmentation
// si on commente la ligne gris[5]=6;, OK tout le temps...

const int MAXI = 1600;

int main()
{
int gris[MAXI*MAXI]; // c'est pareil avec [MAXI][MAXI]


Tu crées un tableau de 2560000 int, soit, en supposant des int à 4
octets, environ 10Mo.
Sans être énorme, en effet, ton OS peut être configuré pour refuser
d'allouer 10Mo dans l'espace d'allocation des variables automatiques
(souvent la pile).


J'entends ça souvent dernièrement. Quels sont ces OS ? Je ne
l'ai pas essayé récemment, mais j'ai déjà alloué des tableaux de
plus d'un Go sous Solaris (sur Sparc).


Sur la pile? C'est possible si tu joues avec ulimit. Mais je le
deconseille parce que
- c'est une chose de plus a documenter
- l'espace (virtuel) pour la pile est reserve (au moins sous
Solaris) et entre en conflit avec les allocations dynamiques.
Permettre des grosses piles limite donc la place disponible pour
le reste

(Je sais que HP/UX avait des limites assez bas, mais il n'y a pas de
raison sur un Sparc ou un Intel de ne pas permettre pratiquement
tout l'espace adressable dans un processus mono-thread.)


Le PA-RISC a un systeme de segments. Si j'ai bonne memoire -- je n'y
touche pas tellement -- c'est penible mais possible d'avoir autre
chose que 1 GB pour la pile, 1 GB pour le code, 1GB pour le tas et 1
GB pour l'OS. Naturellement, ulimit limite encore plus certaines
choses.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org



Avatar
Jean-Marc Bourguet
"Arnaud Debaene" writes:

James Kanze wrote:

J'entends ça souvent dernièrement. Quels sont ces OS ? Je ne
l'ai pas essayé récemment, mais j'ai déjà alloué des tableaux de
plus d'un Go sous Solaris (sur Sparc). (Je sais que HP/UX avait
des limites assez bas, mais il n'y a pas de raison sur un Sparc
ou un Intel de ne pas permettre pratiquement tout l'espace
adressable dans un processus mono-thread.)
Sous Windows : la taille maximale de la pile est fixée à l'édition de lien

pour le thread principal, et par programmation lors du démarrage des threads
secondaires. Avec les outils courants, la valeur par défaut est de 1 MO pour
la pile du thread principal.

Je pense que sur les processeur Intel, c'est lié à la pile qui grossit "vers
le bas".


Je ne vois pas le rapport. Quand on a que deux zones qui grossissent:
le tas et la pile, que la pile grossisse architecturellement dans un
sens ou dans l'autre, le tas on le controle et on peut le faire
occuper l'autre cote de la grosse zone libre.

En pratique naturellement, on a plus de deux zones (les piles des
autres threads et les bibliotheques chargees dynamiquement) et on a un
certain avantage a limiter la pile principale (la plupart du temps,
une pile qui grossit exagerement, c'est du a une recursivite mal geree
et pas a autre chose, l'arreter tot plutot que tard n'est pas un mal;
naturellement, c'est une prophetie auto-realisatrice: les programmeurs
savent que la pile est limitee donc utilisent de l'allocation
dynamique pour les gros objets).

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Jean-Marc Bourguet
writes:

- l'espace (virtuel) pour la pile est reserve (au moins
sous Solaris) et entre en conflit avec les allocations
dynamiques. Permettre des grosses piles limite donc la
place disponible pour le reste


Est-ce que le système alloue ulimit -s sur la pile dès le
démarrage du programme ?


Non.

Est-ce que le système en alloue l'espace d'adressage dans le
processus selon ulimit -s ? Là, aussi, j'ai mes doutes, parce qu'il
y a toujours le problème si ulimit -s est illimité.


De memoire, en variant ulimit -s, la somme de cette limite et de ce
que j'etais capable d'allouer avec malloc etait a peut pres une
constante et ne pas mettre de limite pour -s etait equivalent a en
mettre une a 2GB. On avait des donnees sur lesquels on s'arraitait
par manque de memoire avec un ulimit -s unlimited et pas avec ulimit
-s 8192.

Ce serait facile de refaire un petit programme qui fait des malloc
jusqu'a ce qu'ils echouent et de le lancer avec differentes valeur de
ulimit -s.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Jean-Marc Bourguet
writes:

Jean-Marc Bourguet wrote:
writes:

- l'espace (virtuel) pour la pile est reserve (au moins
sous Solaris) et entre en conflit avec les
allocations dynamiques. Permettre des grosses piles
limite donc la place disponible pour le reste


Est-ce que le système alloue ulimit -s sur la pile dès le
démarrage du programme ?


Non.

Est-ce que le système en alloue l'espace d'adressage dans le
processus selon ulimit -s ? Là, aussi, j'ai mes doutes,
parce qu'il y a toujours le problème si ulimit -s est
illimité.


De memoire, en variant ulimit -s, la somme de cette limite et
de ce que j'etais capable d'allouer avec malloc etait a peut
pres une constante et ne pas mettre de limite pour -s etait
equivalent a en mettre une a 2GB. On avait des donnees sur
lesquels on s'arraitait par manque de memoire avec un ulimit
-s unlimited et pas avec ulimit -s 8192.

Ce serait facile de refaire un petit programme qui fait des
malloc jusqu'a ce qu'ils echouent et de le lancer avec
differentes valeur de ulimit -s.


Pas si facile que ça. D'abord il faut avoir une machine avec
assez de mémoire:-).


C'est pas un probleme ici... on a reellement besoin du 64 bits dans
certains cas donc on a les machines qu'il faut.

$ cat testmem.c
#include <stdlib.h>
#include <stdio.h>
#include <sys/resource.h>

int main(int argc, char* argv[])
{
unsigned long allocated = 0;
unsigned long quantum = 128*1024*1024;
void* data;

struct rlimit mylimits;

if (getrlimit(RLIMIT_DATA, &mylimits) != 0) {
perror("getrlimit failed");
} else {
printf("rlimit(RLIMIT_DATA)=%lu/%lun",
mylimits.rlim_cur, mylimits.rlim_max);
}
if (getrlimit(RLIMIT_STACK, &mylimits) != 0) {
perror("getrlimit failed");
} else {
printf("rlimit(RLIMIT_STACK)=%lu/%lun",
mylimits.rlim_cur, mylimits.rlim_max);
}
while (quantum != 0) {
data = malloc(quantum);
if (data == 0) {
quantum = quantum/2;
} else {
allocated += quantum;
}
}
printf("Unable to allocate more than %lu bytesn", allocated);
printf("STACK+allocated= %lu bytesn", allocated+mylimits.rlim_cur);
}
$ limit
cputime unlimited
filesize unlimited
datasize unlimited
stacksize 8192 kbytes
coredumpsize 0 kbytes
vmemoryuse unlimited
descriptors 1024
$ ./testmem
rlimit(RLIMIT_DATA)!47483647/2147483647
rlimit(RLIMIT_STACK)ƒ89120/2147483647
Unable to allocate more than 4280671872 bytes
STACK+allocated= 4289060992 bytes
$ limit stack 81920
$ ./testmem
rlimit(RLIMIT_DATA)!47483647/2147483647
rlimit(RLIMIT_STACK)ƒ886592/2147483647
Unable to allocate more than 4205174400 bytes
STACK+allocated= 4289060992 bytes
$ limit stack 819200
$ ./testmem
rlimit(RLIMIT_DATA)!47483647/2147483647
rlimit(RLIMIT_STACK)ƒ8861312/2147483647
Unable to allocate more than 3450199744 bytes
STACK+allocated= 4289061056 bytes
$ limit stack unlimited
$ ./testmem
rlimit(RLIMIT_DATA)!47483647/2147483647
rlimit(RLIMIT_STACK)!47483647/2147483647
Unable to allocate more than 2141576960 bytes
STACK+allocated= 4289060607 bytes

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org