Existe-t-il une implémentation sans stack ou sans effort de C ++?

La norme C ++ ne mentionne rien à propos de la stack ou du tas, elles sont spécifiques à l’implémentation , ce qui est vrai.

Même s’ils ne font pas partie de la norme C ++, nous finissons toujours par les utiliser, à tel point que c’est comme s’ils faisaient partie du langage lui-même et devaient être pris en compte pour des objectives de mémoire ou de performances.

D’où ma question: existe-t-il des implémentations de C ++ qui n’utilisent pas les stacks et les tas?

D’autres ont déjà donné de bonnes réponses à propos du tas, alors je vais le laisser tranquille.

Certaines implémentations (sur les ordinateurs centraux IBM, par exemple) n’utilisent pas une stack comme le pensent la plupart des gens, pour la simple raison que le matériel ne la prend pas en charge. Au lieu de cela, lorsque vous appelez une fonction, un enregistrement d’activation (c’est-à-dire un espace pour les parameters locaux, les arguments et l’adresse de retour) est alloué à partir de (la version de) le segment de mémoire. Ces enregistrements d’activation sont intégrés à une liste liée.

D’un sharepoint vue purement abstrait, il s’agit certainement d’une stack – elle prend en charge la sémantique dernier entré, premier sorti, comme toute autre stack. Vous devez toutefois regarder cela assez abstraitement pour appeler cela une stack. Si vous montrez aux gens un diagramme des blocs de mémoire reliés entre eux, je pense qu’il est prudent de deviner que la plupart des programmeurs le décriraient comme une liste chaînée. Si vous les avez poussés, je pense que la plupart jugeraient quelque chose comme “ouais, vous pouvez l’ utiliser comme une stack, mais c’est toujours une liste chaînée”.

La norme C ++ ne mentionne rien à propos de la stack ou du tas

C’est effectivement le cas – mais pas dans ces termes, et sans spécifier comment les stacks et les tas sont mis en œuvre.

En C ++ 03, il existe trois types de variables:

  1. Celles avec une durée de stockage statique (3.7.1). Ce sont “dans la scope” pour la durée du programme.
  2. Celles avec durée de stockage automatique (3.7.2). Celles-ci ne sont incluses que dans le contexte dans lequel elles sont déclarées. Lorsqu’elles tombent en dehors de la scope, la variable est détruite et désallouée.
  3. Celles avec durée de stockage dynamic (3.7.3). Ceux-ci sont créés avec une new expression et détruits avec une delete . les objects eux-mêmes n’ont pas de scope, en ce sens que leur durée de vie n’est pas liée au contexte dans lequel ils ont été créés. Les pointeurs immédiats vers ces objects sont, bien entendu, délimités. Les pointeurs ont une durée de stockage automatique ou rarement (et généralement erronée) statique.

“Stack” et “Heap” ne sont en réalité que là où vivent ensuite les deux derniers types d’objects. Ce sont des détails d’implémentation dépendant de la plate-forme qui répondent aux exigences linguistiques.

Donc, techniquement, vous avez raison. La norme ne dit rien sur les tas et les stacks. Mais cela en dit long sur différents types de durée de stockage, ce qui nécessite une sorte d’implémentation sur une vraie plate-forme. Sur la plupart des matériels de type PC modernes, cela est implémenté en tant que tas et stacks. Les différents types de durée de stockage peuvent-ils être mis en œuvre sur une plate-forme sans utiliser de tas ou de stacks? Tout est possible – je suppose que cela est possible. Mais quelle que soit cette implémentation, elle aurait probablement des caractéristiques similaires à au moins l’une des deux.

En plus de tout cela, il est à noter que la norme exige à la fois une durée de stockage automatique et une durée de stockage dynamic. Toute implémentation de langage qui ne répond pas à ces deux exigences ne serait pas C ++. Ce pourrait être proche, mais ce ne serait pas vraiment C ++.

Pour les petits environnements de programmation, par exemple la plate-forme arduino qui était basée sur un microprocesseur Atmel 8K (maintenant 32K ou plus), un segment de mémoire n’est pas implémenté et aucun nouvel opérateur n’a été défini par la bibliothèque. Tous les objects sont créés statiquement ou sur la stack. Vous perdez les avantages de la bibliothèque standard, mais vous pouvez utiliser un langage orienté object pour programmer une très petite plate-forme – par exemple, créer des classes représentant des broches configurées en tant que modes de sortie particuliers ou ports série, créer un object de cette classe en lui donnant le numéro d’identification personnelle puis en appelant des fonctions sur cet object plutôt que de devoir transmettre le numéro d’identification personnelle à vos routines.

Si vous utilisez new sur un arduino, votre programme comstack mais ne crée pas de lien. Le compilateur est g ++ et cible l’ensemble d’instructions avr. Il s’agit donc d’un vrai compilateur C ++. Si vous choisissez de fournir votre propre implémentation, vous pouvez le faire, mais le coût d’une telle implémentation sur une empreinte aussi petite ne vaut pas le gain dans la plupart des cas.

Cela fait essentiellement écho à la réponse de M. TA (+1 BTW). La stack et le tas sont des concepts abstraits.

Les opérateurs new et delete (et free fonctions malloc et free ) ne sont en réalité qu’une interface pour l’abstraction appelée tas. Ainsi, lorsque vous demandez à une implémentation C ++ d’être “sans faille”, vous demandez réellement que cette implémentation ne vous autorise pas à utiliser ces interfaces. Je pense que rien n’empêche une mise en oeuvre d’échouer toujours dans ces interfaces.

L’appel de fonctions et la reprise de l’exécution en cours après le retour de l’appel (et éventuellement la récupération d’une valeur de retour) sont des interfaces pour une abstraction de stack. Lorsque vous demandez à l’implémentation C ++ d’être “sans stack”, vous demandez à l’implémentation C ++ d’empêcher le programme d’effectuer ces actions. Je ne peux pas penser à un moyen conforme pour le compilateur d’imposer cette condition. La langue exige que le code source soit autorisé à définir des fonctions et à définir un code pour appeler des fonctions.

Donc ma réponse en termes de ce qui est possible: “stackless” non, “sans effort” oui.

Il ne peut y avoir d’implémentation sans stack et sans stack puisque C ++ définit des constructions telles que des fonctions et l’opérateur new. L’appel d’une fonction nécessite une stack et le “nouveau” démarrage d’une instance nécessite un tas. Leur mise en œuvre peut différer d’une plate-forme à l’autre, mais l’idée sera la même. Il sera toujours nécessaire d’avoir une zone mémoire pour les objects de l’instance et une autre zone mémoire pour suivre le point d’exécution et la hiérarchie des appels.

Puisque x86 (et x64) ont des facilités pratiques pour ces choses (c’est-à-dire le registre ESP), le compilateur les utilise. D’autres plates-formes peuvent être différentes, mais le résultat final est logiquement équivalent.

J’ose dire qu’il n’existe pas de telle implémentation C ++, mais simplement parce que la stack et le tas sont des abstractions très utiles pour lesquelles pratiquement tous les processeurs du marché fournissent un support matériel pour les rendre très efficaces.

Puisque C ++ vise l’efficacité, les implémentations C ++ en feront usage. De plus, les programmes C ++ ne fonctionnent généralement pas en vase clos. Ils doivent s’intégrer dans l’écosystème de la plate-forme, défini par l’ interface binary d’application de la plate-forme. L’ABI – pour les mêmes raisons – définit la stack et d’autres structures de mémoire auxquelles l’implémentation C ++ devra obéir.

Cependant, supposons que votre programme C ++ cible une plate-forme intégrée simple, de petite taille et aux ressources limitées, avec un microcontrôleur exotique et aucun système d’exploitation (votre application sera le système d’exploitation!) Et aucun processus ou thread.

Pour commencer, la plate-forme peut ne pas fournir de mémoire dynamic du tout. Vous devrez travailler avec un pool de mémoire statique défini au moment de la liaison et développer votre propre gestionnaire d’allocation de mémoire ( new ). C ++ le permet, et dans certains environnements, il est effectivement utilisé.

De plus, le processeur peut être tel que l’abstraction de stack n’est pas très utile et ne mérite donc pas d’être implémentée. Par exemple, des processeurs tels que SPARC définissent un mécanisme de fenêtre de registre glissant qui, combiné à un grand nombre de registres, rend l’utilisation de la stack inefficace pour les appels de fonctions (si vous la regardez, la stack est déjà créée dans HW!).

En bref, toute l’implémentation C ++ utilise la stack, la plupart utilisent le tas, mais la raison est fortement corrélée aux propriétés de la plate-forme.

Oui, principalement des MCU comme Freescale et PIC

2. Les processeurs sans stack sont utilisés maintenant.

Nous ne considérons pas les cœurs comme le font les programmeurs d’assemblages. Nous sums satisfaits des modèles de programmeurs simples, tant que les bases requirejses sont présentes. Une stack n’en fait pas partie: nous avons récemment rencontré plusieurs cœurs sans stack et nous n’avons eu aucun problème à développer des compilateurs C pour eux.

L’eTPU est une unité de traitement du temps améliorée de 24 bits, utilisée dans le contrôle des moteurs de l’automobile et de l’aviation générale et dans le contrôle des processus. eTPU est peut-être un co-processeur, mais il possède un jeu d’instructions complet et un cœur de processeur complet. Il s’agit d’un processeur de milieu de volume: il est probable que vous conduirez ou reviendrez à la maison ce soir grâce à C sur un processeur sans stack.

Nous avons un compilateur C pour l’eTPU basé sur C99 et ISO / IEC 18037. Nous exécutons des suites de tests C standard sur ce processeur.

Le Freescale RS08 est un MCU plus traditionnel sans stack. Dans le processus de “réduction” du kernel HC08 / HCS08, Freescale a supprimé la stack de processeurs. Nous avons consulté l’architecture de RS08 et nous n’avons jamais ressenti le besoin d’insister sur une stack matérielle.

Pour mentionner un autre co-processeur que nous avons consulté, le Freescale XGATE possède un modèle ISA et de programmation très convivial, mais il n’a pas de stack.

Ensuite, il y a le “presque sans stack”. Les PIC de la puce n’ont jamais eu d’emstackment de données, avec seulement une stack de retour d’appel à 8 entrées (ou 16 entrées dans le kernel amélioré 14 bits). Personne ne doute que C est disponible pour les PIC.

Ces composants, en particulier l’eTPU, ont été conçus pour être faciles à comstackr et encourager le code généré par une machine.

Il existe d’autres processeurs non basés sur des stacks, certains créés récemment, couvrant plusieurs applications et utilisant leurs propres compilateurs C. Il existe des pièces sans stack de volume moyen à élevé. Les performances sont généralement la principale raison pour laquelle les pièces ne possèdent pas de stack.

http://www.bytecraft.com/Stack_controversy