| Zeile 1: | Zeile 1: | ||
Da C++ eine Weiterentwicklung von C ist, sollte man sich auch den Wikiartikel zu [[C]] zu Gemüte führen. | Da C++ eine Weiterentwicklung von C ist, sollte man sich auch den Wikiartikel zu [[C]] zu Gemüte führen. | ||
| − | = | + | = Überblick = |
Die meisten C++ Features sind ohne zusätzlichen Aufwand sofort verfügbar. Nur für die folgenden Features werden Hilffunktionen benötigt, welche der C++ Compiler von Haus aus nicht zur Verfügung stellt: | Die meisten C++ Features sind ohne zusätzlichen Aufwand sofort verfügbar. Nur für die folgenden Features werden Hilffunktionen benötigt, welche der C++ Compiler von Haus aus nicht zur Verfügung stellt: | ||
| − | * Startup-Code | + | * [[C++#Startup-Code | Startup-Code]] |
| − | * rein virtuelle Funktionen | + | * [[C++#rein virtuelle Funktionen | rein virtuelle Funktionen]] |
| − | * globale/statische Objekte | + | * [[C++#globale/statische Objekte | globale/statische Objekte]] |
| − | * new/delete | + | * [[C++#new/delete | new/delete]] |
| − | * RTTI (= Runtime type information) | + | * [[C++#RTTI | RTTI (= Runtime type information)]] |
| − | * Exceptions | + | * [[C++#Exceptions | Exceptions]] |
| − | Da jeder Compilerhersteller eine eigene ABI (= Application Binary Interface) zur Verfügung stellt sind auch die | + | Da jeder Compilerhersteller eine eigene ABI (= Application Binary Interface) zur Verfügung stellt sind auch die Funktionsnamen und der Funktionsumfang von Compiler zu Compiler verschieden. |
= Startup-Code = | = Startup-Code = | ||
| Zeile 21: | Zeile 21: | ||
== g++ == | == g++ == | ||
<cpp> | <cpp> | ||
| + | // Lizenz: public domain | ||
| + | |||
extern "C" void __cxa_pure_virtual() | extern "C" void __cxa_pure_virtual() | ||
{ | { | ||
| − | + | // Fehlermeldung anzeigen | |
| − | + | // Programm/Kernel beenden | |
} | } | ||
</cpp> | </cpp> | ||
| Zeile 39: | Zeile 41: | ||
G++ erstellt eine "ctors*" Sektion, welche ein Array aus Funktionszeigern ist. Diese Funktionszeiger zeigen jeweils auf einen Konstruktor. Man muss nun nur dieses Array durchgehen und alle Funktionen aufrufen und schon hat man alle globalen/statischen Objekte initialisiert. | G++ erstellt eine "ctors*" Sektion, welche ein Array aus Funktionszeigern ist. Diese Funktionszeiger zeigen jeweils auf einen Konstruktor. Man muss nun nur dieses Array durchgehen und alle Funktionen aufrufen und schon hat man alle globalen/statischen Objekte initialisiert. | ||
| + | |||
| + | <cpp> | ||
| + | // Lizenz: public domain | ||
| + | |||
| + | // Im Linkerskript definiert | ||
| + | uintptr_t start_ctors; | ||
| + | uintptr_t end_ctors; | ||
| + | |||
| + | // Ruft die Konstruktoren für globale/statische Objekte auf | ||
| + | void initialiseConstructors() | ||
| + | { | ||
| + | uintptr_t *iterator = reinterpret_cast<uintptr_t*>(&start_ctors); | ||
| + | while (iterator < reinterpret_cast<uintptr_t*>(&end_ctors)) | ||
| + | { | ||
| + | void (*fp)(void) = reinterpret_cast<void (*)(void)>(*iterator); | ||
| + | fp(); | ||
| + | iterator++; | ||
| + | } | ||
| + | } | ||
| + | </cpp> | ||
| + | |||
| + | Diese Funktion muss explizit aufgerufen werden bevor globale/statische Objekte verwendet werden. Dies kann beispielsweise im [[C++#Startup-Code | Startup-Code]] geschehen. | ||
=== Destruktoren (ohne --enable-__cxa_atexit und ohne -fuse-cxa-atexit) === | === Destruktoren (ohne --enable-__cxa_atexit und ohne -fuse-cxa-atexit) === | ||
| Zeile 62: | Zeile 86: | ||
<cpp> | <cpp> | ||
| + | // Lizenz: public domain | ||
| + | |||
extern "C" | extern "C" | ||
| − | + | { | |
| − | + | int __cxa_atexit(void (*f)(void *), void *p, void *d); | |
| − | + | void __cxa_finalize(void *d); | |
| − | + | }; | |
void *__dso_handle; | void *__dso_handle; | ||
| Zeile 72: | Zeile 98: | ||
struct object | struct object | ||
{ | { | ||
| − | + | void (*f)(void*); | |
| − | + | void *p; | |
| − | + | void *d; | |
} object[32] = {0}; | } object[32] = {0}; | ||
unsigned int iObject = 0; | unsigned int iObject = 0; | ||
| Zeile 80: | Zeile 106: | ||
int __cxa_atexit(void (*f)(void *), void *p, void *d) | int __cxa_atexit(void (*f)(void *), void *p, void *d) | ||
{ | { | ||
| − | + | if (iObject >= 32) return -1; | |
| − | + | object[iObject].f = f; | |
| − | + | object[iObject].p = p; | |
| − | + | object[iObject].d = d; | |
| − | + | ++iObject; | |
| − | + | return 0; | |
} | } | ||
| Zeile 91: | Zeile 117: | ||
void __cxa_finalize(void *d) | void __cxa_finalize(void *d) | ||
{ | { | ||
| − | + | unsigned int i = iObject; | |
| − | + | for (; i > 0; --i) | |
| − | + | { | |
| − | + | --iObject; | |
| − | + | object[iObject].f(object[iObject].p); | |
| − | + | } | |
} | } | ||
</cpp> | </cpp> | ||
| Zeile 112: | Zeile 138: | ||
void *operator new( size_t size ) | void *operator new( size_t size ) | ||
{ | { | ||
| − | + | return kcalloc( size ); | |
} | } | ||
void *operator new[]( size_t size ) | void *operator new[]( size_t size ) | ||
{ | { | ||
| − | + | return kcalloc( size ); | |
} | } | ||
void operator delete( void *ojb ) | void operator delete( void *ojb ) | ||
{ | { | ||
| − | + | kfree( obj ); | |
} | } | ||
void operator delete[]( void *obj ) | void operator delete[]( void *obj ) | ||
{ | { | ||
| − | + | kfree( obj ); | |
} | } | ||
</cpp> | </cpp> | ||
= RTTI = | = RTTI = | ||
| + | RTTI (Runtime Type Information) wird am besten innerhalb des Kernels komplett deaktiviert. Mit g++ geschieht dies mittels des Kommandozeilenparameter ''-fno-rtti''. | ||
| + | |||
= Exceptions = | = Exceptions = | ||
| + | |||
| + | Exceptions sollten auch am besten innerhalb des Kernels deaktiviert werden. Mit g++ können Exceptions über den Kommandozeilenparameter ''-fno-exceptions'' deaktiviert werden. | ||
| + | |||
= Links = | = Links = | ||
* [http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2006/n2135.pdf Draft des C++ Standards] | * [http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2006/n2135.pdf Draft des C++ Standards] | ||