2009-09-25 4 views
1

Je joue autour de l'empilement sur un gcc exécutant le système Ubuntu 9.04 4.3.3 avec la variable de noyau randomize_va_space mis à 0 (/ proc/sys/kernel/randomize_va_space)taille du tableau Déclaration de la variable automatique de paramètre d'entrée

Si je déclare une variable auto dans une fonction qui est un tableau dont la taille est déterminée par l'entrée, comment le tableau est-il alloué sur la pile?

La fonction ressemble à ceci -

int fun(int i) { 
    char a[i]; 
    char *ptr; 

    printf("a - %p ptr - %p\n", a, &ptr); 
    printf("Difference - %ld\n", ((unsigned long)&ptr - (unsigned long)a); 
    printf("sizeof(a) - %d\n\n", sizeof(a)); 
} 

L'opérateur sizeof lorsqu'il est passé l'un tableau retourne la taille attendue (même -1) donc je me demandais pourquoi le tableau prend beaucoup de place sur la pile , et deuxièmement, pourquoi sizeof() renvoie -1?

La sortie ressemble à ceci -

a - 0xbffff4c0 ptr - 0xbffff4fc 
Difference - 60 
sizeof(a) - -1 

a - 0xbffff4c0 ptr - 0xbffff4fc 
Difference - 60 
sizeof(a) - 0 

a - 0xbffff4c0 ptr - 0xbffff4fc 
Difference - 60 
sizeof(a) - 1 

a - 0xbffff4b0 ptr - 0xbffff4fc 
Difference - 76 
sizeof(a) - 2 

a - 0xbffff4b0 ptr - 0xbffff4fc 
Difference - 76 
sizeof(a) - 3 

a - 0xbffff4b0 ptr - 0xbffff4fc 
Difference - 76 
sizeof(a) - 4 
+0

Cela ne devrait pas compiler. Vous pouvez uniquement déclarer des tableaux de taille constante sur la pile. Normalement, vous auriez besoin de faire char * a = new char [i]; –

+0

Je pensais aussi, mais il compile et fonctionne très bien. – aks

+0

Je me demande quel compilateur vous utilisez ...: P –

Répondre

5

Les matrices automatiques à longueur variable ont été introduites dans C en C99. Le tableau est alloué en ajustant le pointeur de pile par la taille du tableau, tout comme une variable automatique normale - la seule différence est que la taille de l'ajustement du pointeur de pile et le décalage de a du pointeur de trame ne sont pas des constantes peut être calculé au moment de la compilation - ils doivent être calculés lors de l'exécution.

De même, pour sizeof de fonctionner correctement sur des tableaux de longueur variable, lorsqu'il est appliqué à un tel tableau, il ne peut pas non plus être calculé au moment de la compilation. La taille allouée de a doit être mémorisée lors de la saisie de la portée.

Ce sont ces informations d'entretien - le nombre, la taille et le décalage des tableaux automatiques de longueur variable - qui sont conservés sur la pile dans l'espace supplémentaire que vous voyez entre a et ptr. Il y a peut-être aussi un pointeur de frame sauvegardé supplémentaire - vous devriez vraiment creuser dans la source pour que votre compilateur puisse le découvrir.

Oh, et la raison pour laquelle vous voyez -1 de sizeof est parce que vous l'imprimer de manière incorrecte avec le prescripteur %d - utiliser %zu pour size_t.

0

Je suis surpris de cette compilation. Le compilateur ne peut pas allouer de la mémoire sur la pile au moment de la compilation, à moins de connaître le montant à allouer. Lorsque vous allouez en utilisant 'new' ou 'malloc', la mémoire est allouée sur le tas. Voici ce que je reçois quand je compile ceci:

alloc.c (2): C2057 d'erreur: expression constante attendue
alloc.c (2): erreur C2466: ne peut pas allouer un tableau de taille constante 0
alloc. c (2): erreur C2133: 'a': taille inconnue
alloc.c (7): avertissement C4034: sizeof renvoie 0

Je pense que le reste de la question est sans objet.

+0

Les compilateurs peuvent certainement allouer de la mémoire sur la pile avec une taille déterminée à l'exécution - c'est ce que alloca() fait sur les compilateurs qui le supportent. –

1

Un compilateur qui prend en charge la sémantique des matrices de variables C99 devrait compiler ceci (bien que je n'ai pas vraiment beaucoup d'expérience avec les matrices var).

Quelle est la valeur de i qui est transmise pour chacune de ces itérations? Cela aiderait à expliquer pourquoi aizeof() retourne -1 dans certains cas.

Selon cette page:

tableaux de longueur variable travaillent dans GCC ligne principale, mais selon:

ils étaient cassé dans GCC 4.3. Cela explique probablement les problèmes que vous voyez avec sizeof().

+0

La valeur renvoyée par sizeof() est la valeur qui a été transmise à la fonction en tant que 'i'. – aks

+0

La norme C99 indique que chaque fois que l'expression dans la déclaration de tableau est évaluée, elle doit avoir une valeur supérieure à 0. Lorsque vous passez à -1 ou 0, vous obtenez un comportement indéfini - dans ce cas vous obtenez un sizeof() = = -1 ou 0. Quant à savoir pourquoi le tableau semble prendre autant d'espace même pour les petites valeurs de i - je ne sais pas (rappelez-vous, les docs de statut GCC C99 disent que le support a été brisé). –

Questions connexes