Für ein sehr ressourcenbeschränktes Ziel wie 4 KB RAM würde ich das Wasser mit einigen Beispielen testen, bevor ich viel Aufwand unternehme, der nicht einfach in eine reine ANSI C-Implementierung zurückportiert werden kann.
Die Arbeitsgruppe Embedded C ++ schlug eine Standarduntermenge der Sprache und eine dazugehörige Standarduntermenge der Standardbibliothek vor. Ich habe diese Bemühungen leider aus den Augen verloren, als das C User's Journal starb. Es sieht so aus, als gäbe es einen Artikel bei Wikipedia und das Komitee existiert noch.
In einer eingebetteten Umgebung müssen Sie bei der Speicherzuweisung wirklich vorsichtig sein. Um diese Sorgfalt durchzusetzen, müssen Sie möglicherweise das Globale operator new()
und seine Freunde für etwas definieren, das nicht einmal verknüpft werden kann, damit Sie wissen, dass es nicht verwendet wird. Die Platzierung new
hingegen ist wahrscheinlich Ihr Freund, wenn sie mit Bedacht zusammen mit einem stabilen, threadsicheren und latenzgarantierten Zuweisungsschema verwendet wird.
Inline-Funktionen verursachen keine großen Probleme, es sei denn, sie sind groß genug, um eigentlich echte Funktionen zu sein. Natürlich hatten die Makros, die sie ersetzten, das gleiche Problem.
Auch Vorlagen verursachen möglicherweise kein Problem, es sei denn, ihre Instanziierung wird amok ausgeführt. Überprüfen Sie für jede Vorlage, die Sie verwenden, Ihren generierten Code (die Link-Map enthält möglicherweise genügend Hinweise), um sicherzustellen, dass nur die von Ihnen beabsichtigten Instanziierungen ausgeführt wurden.
Ein weiteres Problem, das auftreten kann, ist die Kompatibilität mit Ihrem Debugger. Es ist nicht ungewöhnlich, dass ein ansonsten verwendbarer Hardware-Debugger die Interaktion mit dem ursprünglichen Quellcode nur sehr eingeschränkt unterstützt. Wenn Sie in Assembly effektiv debuggen müssen, kann die interessante Namensverknüpfung von C ++ die Aufgabe zusätzlich verwirren.
RTTI, dynamische Casts, Mehrfachvererbung, starker Polymorphismus und Ausnahmen verursachen für ihre Verwendung einige Laufzeitkosten. Einige dieser Funktionen kosten das gesamte Programm, wenn sie verwendet werden, andere erhöhen lediglich das Gewicht der Klassen, die sie benötigen. Kennen Sie den Unterschied und wählen Sie erweiterte Funktionen mit Bedacht aus, wobei Sie mindestens eine flüchtige Kosten-Nutzen-Analyse kennen.
In einer kleinen eingebetteten Umgebung stellen Sie entweder eine direkte Verbindung zu einem Echtzeitkern her oder laufen direkt auf der Hardware. In beiden Fällen müssen Sie sicherstellen, dass Ihr Laufzeit-Startcode die C ++ - spezifischen Startaufgaben korrekt behandelt. Dies ist möglicherweise so einfach wie die Verwendung der richtigen Linker-Optionen. Da es jedoch üblich ist, die direkte Kontrolle über die Quelle zum Einschalt-Reset-Einstiegspunkt zu haben, müssen Sie dies möglicherweise überprüfen, um sicherzustellen, dass alles funktioniert. Auf einer ColdFire-Plattform, an der ich gearbeitet habe, wurden die Entwicklertools beispielsweise mit einem CRT0.S-Modul geliefert, in dem die C ++ - Initialisierer vorhanden waren, das jedoch auskommentiert wurde. Wenn ich es direkt aus der Box verwendet hätte, wäre ich von globalen Objekten verwirrt worden, deren Konstruktoren überhaupt nicht ausgeführt worden waren.
In einer eingebetteten Umgebung ist es häufig erforderlich, Hardwaregeräte zu initialisieren, bevor sie verwendet werden können. Wenn es kein Betriebssystem und keinen Bootloader gibt, ist dies Ihr Code, der dies tut. Sie müssen sich daran erinnern, dass Konstruktoren für globale Objekte ausgeführt werden, bevor sie main()
aufgerufen werden. Daher müssen Sie Ihre lokale CRT0.S (oder eine entsprechende Entsprechung) ändern, um die Hardware-Initialisierung durchzuführen, bevor die globalen Konstruktoren selbst aufgerufen werden. Offensichtlich ist die Spitze main()
viel zu spät.