Est-ce une mauvaise pratique de déclarer un tableau au milieu d’une fonction?

dans le but de demander seulement ce que je cherche vraiment ici … Je ne suis vraiment concerné que si c’est considéré comme une mauvaise pratique ou de ne pas déclarer un tableau comme ci-dessous où la taille pourrait varier. Si c’est le cas … je préférerais généralement malloc ().

void MyFunction() { int size; //do a bunch of stuff size = 10; //but could have been something else int array[size]; //do more stuff... } 

Généralement oui, c’est une mauvaise pratique, bien que les nouvelles normes vous permettent d’utiliser cette syntaxe. À mon avis, vous devez allouer (sur le tas) la mémoire que vous souhaitez utiliser et la libérer une fois que vous avez terminé. Puisqu’il n’y a pas de moyen portable de vérifier si la stack est suffisante pour contenir ce tableau, vous devriez utiliser certaines méthodes qui peuvent être vraiment vérifiées – comme malloc / calloc & free. Dans le monde intégré, la taille de la stack peut être un problème.

Si vous êtes inquiet à propos de la fragmentation, vous pouvez créer votre propre allocateur de mémoire, mais ceci est une histoire totalement différente.

Ça dépend. Le premier n’est clairement pas ce que j’appellerais “convenable”, et le second n’est que dans des circonstances assez limitées.

Dans le premier cas, vous ne devriez pas lancer le retour de malloc en C – vous risqueriez ainsi de dissimuler le bogue d’omission accidentelle de l’inclusion de l’en-tête correct ( ).

Dans le second cas, vous limitez le code à C99 ou à une extension gcc. Tant que vous en êtes conscient et que cela fonctionne pour vous, tout va bien, mais ce n’est pas ce que j’appellerais un idéal de portabilité.

En ce qui concerne ce que vous demandez vraiment: avec le bogue mineur mentionné ci-dessus corrigé, le premier est portable, mais peut être plus lent que vous le souhaitez. Si le second est suffisamment portable pour vos besoins, il sera normalement plus rapide.

Pour votre question, je pense que chacun a ses avantages et ses inconvénients.

Allocation dynamic:
Lent, mais vous pouvez détecter quand il n’y a pas de mémoire à donner à votre programmeur en vérifiant le pointeur.

Allocation de stack:
Seulement en C99 et il est extrêmement rapide, mais en cas de stackoverflow, vous n’avez pas de chance.

En résumé, lorsque vous avez besoin d’un petit tableau, réservez-le sur la stack. Sinon, utilisez judicieusement la mémoire dynamic.

L’argument contre les VLA s’explique par le fait qu’il est absolument néfaste de déborder de la stack et que lorsque vous avez suffisamment réfléchi / vérifié pour les rendre sûres, vous avez suffisamment réfléchi / vérifié pour utiliser un tableau de taille fixe:

1) Pour pouvoir utiliser les VLA en toute sécurité, vous devez savoir qu’il ya suffisamment de stack disponible.

2) Dans la grande majorité des cas, si vous savez qu’il y a suffisamment de stack, vous connaissez une limite supérieure de la size requirejse et vous savez (ou du moins êtes prêt à deviner ou avez besoin) une limite inférieure de la stack disponible. et l’un est plus petit que l’autre. Il suffit donc d’utiliser un tableau de taille fixe.

3) Dans la grande majorité des rares cas qui ne sont pas aussi simples, vous utilisez plusieurs VLA (peut-être un dans chaque appel d’une fonction récursive), et vous connaissez une limite supérieure de leur taille totale , qui est inférieure à une limite inférieure sur la stack disponible. Vous pouvez donc utiliser un tableau de taille fixe et le diviser en plusieurs parties selon les besoins.

4) Si jamais vous rencontrez l’un des cas restants, dans une situation où la performance de malloc est inacceptable, faites le moi savoir …

Il peut être plus pratique, à partir du POV du code source, d’utiliser des VLA. Par exemple, vous pouvez utiliser sizeof (dans la scope de définition) au lieu de conserver la taille dans une variable, et cette entreprise qui divise un tableau en fragments peut nécessiter la transmission d’un paramètre supplémentaire. Il y a donc parfois un petit gain de commodité.

Il est également plus facile de rater le fait que vous utilisiez une quantité énorme de stack, générant un comportement indéfini, si au lieu d’un int buf[1920*1024] ou d’un int buf[MAX_IMG_SIZE] plutôt effrayant, vous avez un int buf[img->size] . Cela fonctionne bien jusqu’à la première fois que vous gérez une grande image. C’est en gros une question de test approprié, mais si vous manquez quelques entrées difficiles, alors ce ne sera pas la première ou la dernière suite de tests à le faire. Je trouve qu’un tableau de taille fixe me rappelle soit de mettre en place des contrôles d’entrée de taille fixe, soit de le remplacer par une allocation dynamic et de ne plus avoir à nous soucier de savoir si elle convient à la stack. Il n’y a pas d’option valable pour le mettre sur la stack et ne pas s’inquiéter s’il convient …

deux points d’un sharepoint vue UNIX / C –

malloc n’est lent que lorsque vous le forcez à appeler brk (). Cela signifie que pour des tableaux raisonnables, c’est la même chose que l’allocation d’espace de stack pour une variable. En passant, lorsque vous utilisez la méthode n ° 2 (via alloca et dans le code libc que j’ai vu), invoque également brk () pour des objects énormes. Donc c’est un lavage. Remarque: avec # 2 & # 1, vous devez toujours appeler directement ou indirectement un appel de type memset pour mettre à zéro les octets du tableau. Ceci est juste une note de côté au vrai problème (IMO):

Le vrai problème est les memory leaks. alloca se nettoie d’elle-même lorsque la fonction est rétablie, de sorte que # 2 est moins susceptible de poser problème. Avec malloc / calloc, vous devez appeler gratuitement () ou commencer une fuite.