Pourquoi ce programme ne plante-t-il pas sur Mac ?

Le
thomas
Il est censé, non ? (allocation mémoire impossible car limitée avec
setrlimit).

En tout cas sous Linux il plante

#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
struct rlimit lim;
int i;

if(getrlimit(RLIMIT_AS, &lim) == -1) return 1;
printf("%d", lim.rlim_cur);

lim.rlim_cur = lim.rlim_max = 100 * 1024;
if(setrlimit(RLIMIT_AS, &lim) == -1) return 2;

if(getrlimit(RLIMIT_AS, &lim) == -1) return 1;
printf("%d", lim.rlim_cur);

char *v = malloc(100000000);
for (i=1;i<1000000;i++)
v[i]=(v[i-1]+3)%200; // pour pas que le malloc se fasse optimiser,
//on sait jamais
printf("%d",42);

}

--
Thomas Deniau
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 2
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Vincent Lefevre
Le #504327
Dans l'article Thomas Deniau
[...]
char *v = malloc(100000000);
for (i=1;i<1000000;i++)
v[i]=(v[i-1]+3)%200; // pour pas que le malloc se fasse optimiser,
//on sait jamais
printf("%dn",42);

}


Les valeurs de v[i] n'ont "aucun" effet sur le programme, donc
l'optimisation est valide. De plus, ton programme a un comportement
indéfini... Si tu veux voir si la mémoire a pu être allouée, il faut
tester si v est nul avant la boucle. C'est la première chose à faire.
De plus, je pense que tu veux initialiser v[0] et afficher v[999999]
pour être à peu près sûr qu'il n'y aura pas d'optimisation.

--
Vincent Lefèvre 100% accessible validated (X)HTML - Blog: Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)

thomas
Le #504326
Vincent Lefevre
Les valeurs de v[i] n'ont "aucun" effet sur le programme, donc
l'optimisation est valide. De plus, ton programme a un comportement
indéfini... Si tu veux voir si la mémoire a pu être allouée, il faut
tester si v est nul avant la boucle. C'est la première chose à faire.
De plus, je pense que tu veux initialiser v[0] et afficher v[999999]
pour être à peu près sûr qu'il n'y aura pas d'optimisation.


Je ne pense pas que ce soit un problème d'optimisation, même avec -O0
j'ai le problème. J'ai plutôt l'impression, d'après ce que je lis dans
le man et sur le net, que la gestion des limites d'OS X est bizarre et
qu'il laisse le programme allouer ce qu'il veut, en se réservant le
droit de le killer le jour où l'OS aura besoin de RAM, si jamais il a
dépassé sa limite.

J'essaie donc d'intercepter malloc() et de savoir combien de mémoire
utilise mon programme via la fonction task_info(), mais pour récupérer
la tâche courante, il semble qu'il faille utiliser :

task_for_pid (current_task(), getpid(), &task)

et ce truc là, au lieu de me renvoyer KERN_SUCCESS, me fait "os/kern
failure".

Quelqu'un a une idée ?

Eric Levenez
Le #506981
Le 31/01/08 12:59, dans « Thomas Deniau »
Je ne pense pas que ce soit un problème d'optimisation, même avec -O0
j'ai le problème. J'ai plutôt l'impression, d'après ce que je lis dans
le man et sur le net, que la gestion des limites d'OS X est bizarre et
qu'il laisse le programme allouer ce qu'il veut, en se réservant le
droit de le killer le jour où l'OS aura besoin de RAM, si jamais il a
dépassé sa limite.


Cela n'a rien de bizarre, c'est un choix d'implémentation. L'allocation de
la mémoire n'aura lieu qu'au moment de l'utilisation. Il n'y a pas de
réservation comme sur les dernières versions de Linux si c'est cela que tu
veux dire. Il y a du pour et du contre aux 2 méthodes.

C'est la même chose avec les pools zfs par exemple. Et la aussi c'est
"normal" car c'est un choix d'implémentation.

--
Éric Lévénez -- Unix is not only an OS, it's a way of life.

thomas
Le #506980
Eric Levenez
Cela n'a rien de bizarre, c'est un choix d'implémentation. L'allocation de
la mémoire n'aura lieu qu'au moment de l'utilisation. Il n'y a pas de
réservation comme sur les dernières versions de Linux si c'est cela que tu
veux dire. Il y a du pour et du contre aux 2 méthodes.

C'est la même chose avec les pools zfs par exemple. Et la aussi c'est
"normal" car c'est un choix d'implémentation.


Et comment je peux faire pour être sûr qu'on ne réserve pas plus qu'une
taille donnée ?

Si c'est impossible, que se passera-t-il lorsque j'utiliserai
effectivement plus de ram qu'autorisé par setrlimit() ? Je chope un
signal ?

C'est pour un vérificateur d'algorithmes (pour un concours de
programmation), qui doit être sûr qu'on ne dépasse pas une certaine
taille en mémoire...

Merci !

--
Thomas Deniau

luc
Le #506979
Thomas Deniau
Il est censé, non ? (allocation mémoire impossible car limitée avec
setrlimit).


"The setrlimit() administrative limits are not enforced except for
certain ones which are enforcible in BSD code. Those which would require
enforcement in Mach code (VM-based enforcement or scheduler- based
enforcement) are not currently enforced at all."


Le post date de 2005, il semblerait qu'il soit toujours d'actualité :)

--
Luc Heinrich

thomas
Le #506978
Luc Heinrich
"The setrlimit() administrative limits are not enforced except for
certain ones which are enforcible in BSD code. Those which would require
enforcement in Mach code (VM-based enforcement or scheduler- based
enforcement) are not currently enforced at all."


Le post date de 2005, il semblerait qu'il soit toujours d'actualité :)


Merci...
je suis bien dans la mouise.

Je vais essayer le coup du thread via une librairie chargée
automatiquement dans le code avec DYLD_INSERT_LIBRARIES, et qui compare
le getrlimit() à la RSIZE actuellement utilisée (récupérée avec
task_info()). Mais bon...

Vincent Lefevre
Le #506752
Dans l'article Eric Levenez
Cela n'a rien de bizarre, c'est un choix d'implémentation.
L'allocation de la mémoire n'aura lieu qu'au moment de
l'utilisation.


C'est tout de même à la limite de la conformité avec la norme C (qui
dit qu'au retour de malloc, on obtient soit un pointeur nul, soit un
pointeur vers l'espace ***alloué***). Ce choix a quand même le gros
problème de ne pas pouvoir réagir proprement.

Il n'y a pas de réservation comme sur les dernières versions de
Linux si c'est cela que tu veux dire.


Sur les dernières versions de Linux, c'est configurable.

--
Vincent Lefèvre 100% accessible validated (X)HTML - Blog: Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)

Vincent Lefevre
Le #506751
Dans l'article Thomas Deniau
Et comment je peux faire pour être sûr qu'on ne réserve pas plus qu'une
taille donnée ?

Si c'est impossible, que se passera-t-il lorsque j'utiliserai
effectivement plus de ram qu'autorisé par setrlimit() ? Je chope un
signal ?

C'est pour un vérificateur d'algorithmes (pour un concours de
programmation), qui doit être sûr qu'on ne dépasse pas une certaine
taille en mémoire...


Dans ce cas, il faut aussi que tu traites les cas où les programmeurs
vont utiliser la pile pour stocker plein de données. Là je pense que
le programme devrait recevoir un signal en cas de dépassement des
ressources.

--
Vincent Lefèvre 100% accessible validated (X)HTML - Blog: Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)

Eric Levenez
Le #506750
Le 02/02/08 22:58, dans Lefevre »
Dans l'article Eric Levenez
Cela n'a rien de bizarre, c'est un choix d'implémentation.
L'allocation de la mémoire n'aura lieu qu'au moment de
l'utilisation.


C'est tout de même à la limite de la conformité avec la norme C (qui
dit qu'au retour de malloc, on obtient soit un pointeur nul, soit un
pointeur vers l'espace ***alloué***).


Malloc retourne un pointeur sur un objet alloué mais rien ne dit que
l'allocation doit être physique ou virtuelle. Et souvent sur Unix l'espace
n'est pas alloué mais juste réservé.

Ce choix a quand même le gros
problème de ne pas pouvoir réagir proprement.


"proprement" ? Ce choix a l'avantage d'être dynamique et est en concordance
avec le swap qui n'utilise pas une place limitée par une partition dédiée.
Si on veut vraiment tester sous Mac OS X (ou un autre Unix) la place
retournée par malloc, il suffit de la remplir par un pattern.

Il n'y a pas de réservation comme sur les dernières versions de
Linux si c'est cela que tu veux dire.


Sur les dernières versions de Linux, c'est configurable.


Sur GNU/Linux il y a tellement de noyaux, de malloc différents, de
configurations de l'overcommit, qu'un programme aura du mal à savoir si le
pointeur retourné par malloc pointe sur une zone allouée physiquement.

--
Éric Lévénez -- Unix is not only an OS, it's a way of life.


Vincent Lefevre
Le #506749
Dans l'article Eric Levenez
Le 02/02/08 22:58, dans Lefevre »
Ce choix a quand même le gros
problème de ne pas pouvoir réagir proprement.


"proprement" ? Ce choix a l'avantage d'être dynamique et est en concordance
avec le swap qui n'utilise pas une place limitée par une partition dédiée.
Si on veut vraiment tester sous Mac OS X (ou un autre Unix) la place
retournée par malloc, il suffit de la remplir par un pattern.


Non, ça ne teste rien du tout. Ça force l'allocation, et s'il n'y a pas
assez de mémoire, le programme plante!

Il n'y a pas de réservation comme sur les dernières versions de
Linux si c'est cela que tu veux dire.


Sur les dernières versions de Linux, c'est configurable.


Sur GNU/Linux il y a tellement de noyaux, de malloc différents, de
configurations de l'overcommit, qu'un programme aura du mal à savoir si le
pointeur retourné par malloc pointe sur une zone allouée physiquement.


Le programme n'a pas besoin de savoir. Il suffit juste de tester la
valeur de retour. Et si l'utilisateur a configuré son noyau de manière
à ne pas (trop) surallouer, en général, le programme ne plantera pas
(s'il est bien écrit).

--
Vincent Lefèvre 100% accessible validated (X)HTML - Blog: Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)



Publicité
Poster une réponse
Anonyme