C++ — Änderungen 2775 → 2814

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.
  
−
= Kernelprogrammierung in C++ =
+
= Ü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 Namen und der Funktionsumfang von Compiler zu Compiler verschieden.
+
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
+
  // Fehlermeldung anzeigen
−
    // Programm/Kernel beenden
+
  // 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);
+
  int __cxa_atexit(void (*f)(void *), void *p, void *d);
−
        void __cxa_finalize(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 (*f)(void*);
−
        void *p;
+
  void *p;
−
        void *d;
+
  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;
+
  if (iObject >= 32) return -1;
−
        object[iObject].f = f;
+
  object[iObject].f = f;
−
        object[iObject].p = p;
+
  object[iObject].p = p;
−
        object[iObject].d = d;
+
  object[iObject].d = d;
−
        ++iObject;
+
  ++iObject;
−
        return 0;
+
  return 0;
 
}
 
}
  
Zeile 91: Zeile 117:
 
void __cxa_finalize(void *d)
 
void __cxa_finalize(void *d)
 
{
 
{
−
        unsigned int i = iObject;
+
  unsigned int i = iObject;
−
        for (; i > 0; --i)
+
  for (; i > 0; --i)
−
        {
+
  {
−
                --iObject;
+
    --iObject;
−
                object[iObject].f(object[iObject].p);
+
    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 );
+
  return kcalloc( size );
 
}
 
}
  
 
void *operator new[]( size_t  size )
 
void *operator new[]( size_t  size )
 
{
 
{
−
        return kcalloc( size );
+
  return kcalloc( size );
 
}
 
}
  
 
void operator delete( void *ojb )
 
void operator delete( void *ojb )
 
{
 
{
−
        kfree( obj );
+
  kfree( obj );
 
}
 
}
  
 
void operator delete[]( void *obj )
 
void operator delete[]( void *obj )
 
{
 
{
−
        kfree( 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]