Operator New in CPP

Aus LOMSO
Zur Navigation springen Zur Suche springen
Du bist hier : Wiki home -> Software -> CPP -> Operator New in CPP



Operator New() in C++

In C++ gibt es 3 Varianten des 'operators new()', die sich im Verhalten unterscheiden, wenn kein Speicher mehr angefordert werden kann.

1. Es wird eine Exception 'bad_alloc' geworfen
    new() gibt in diesem Fall nie NULL zurück.
2. Es wird eine Funktion aufgerufen, die mit 'set_new_handler()' gesetzt werden kann
    Jeder Programmabschnitt kann einen eigenen New Handler haben.
    new() gibt in diesem Fall nie NULL zurück und löst auch keine Exception aus.
3. Mit dem C++-Keywort '(nothrow)' kann new() ein Verhalten aufgezwungen werden, wie das in C mit malloc() der Fall ist.
    Es wird 0 im Fehlerfall zurückgegeben.

Bitte beachten:

    NULL ist in C++ anders definiert als in C!
    C++ NULL ist (int)0
    C   NULL ist (void*)0
    In C ist NULL ein Pointer und in C++ ein 'int'.


Variante 1 ist der das Default Verhalten von operator new().

Varianten 1 und 2 können mit C++ Mitteln überladen werden, Variante 3 nicht.

Von Variante 3 rate ich dringend ab, weil die Verantwortung der Kontrolle über den Speicher dem Entwickler übertragen werden muss. Das ist ein Rückfall in die C Welt. Wichtige C++ Mittel werden ausgehebelt, dann sollte man so konsequent sein und auf C++ ganz verzichten.

Vergessene Prüfungen auf NULL sind eine sehr häufige Ursache für unvorhergesehene Programmabstürze, die mit dem Einsatz der Mittel von C++ der Vergangenheit angehören sollten.

Das ist leider in sehr vielen C++ Programmen in der Praxis der Fall. Es wird nicht einmal Variante 3. korrekt implementiert, es wird Variante 1. verwendet, aber, wie in C, auf NULL getestet.

C++ ist aber eine völlig andere Programmiersprache als C. C++ enthält C aus Legacy-Gründen. Es ist aber ein falsches Vorgehen, mit C++ C-Code zu schreiben.

wzbw.

Ein Beispiel aus der Praxis ist unten, Methode: doNewNullFailDemo().

C++ erlaubt mit Variante 2., dem New-Handler, einen 'Single Point of Failure' zu erstellen, an dem die Behandlung von Speichermangel problemorientiert und auf den jeweiligen Programmteil zugeschnitten erfolgen kann.

Variante 2. ist daher zu bevorzugen. Wenn man das nicht will, ist mind. Variante 1. einzusetzen, aber niemals Variante 3. und die Mischform, new() wie in C++ zu verwenden, aber wie in C zu behandeln, verbietet sich von selbst.

Beschreibung von operator new() bei Cplusplus.com


Operator new() bei Microsoft

VC5/6 enthält einen schweren Bug in Bezug auf das korrekte Verhalten von 'opereator new()':

Operator new does not throw a bad_alloc exception on failure in Visual C++

Status bei MS: "This is a bug in Microsoft's implementation of operator new as this in not in conformance with the ANSI C++ Standard."

'operator new() entspricht keiner der 3 Varianten, es ist die falsche (oben in Fett dargestellte) Variante implementiert.

Maw. C++ Programme, die mit VC5/6 (im XP Zeitalter) geschrieben wurden, können nicht portabel sein. Oder, nich schlimmer, Microsoft fällt als Garant für korrekt geschriebenen C++ Code aus.

Besonders tragisch ist es, dass durch die Persistenz von XP, und damit weiteren Existenz von VC6 bei vielen Endkunden, Entwickler gezwungen werden, nichtstandardkonformen C++ Code zu entwickeln.

Es kommt noch schlimmer:

Angeblich ist mit VC2005 dieser Bug beseitigt.

Damit aber die MS gewohnten Entwickler weiterhin nicht portablen Code schreiben können, wurde das Objektmodul nothrownew.obj erfunden, welches das alte und falsche Verhalten bei allen neueren MS-Compilern konserviert. Ich hab das nicht getestet, weil ich seit Jahren den GCC unter Linux einsetze.

Hinweise bei Stackoverflow:

Will new return NULL in any case?

Why would Microsoft still support nothrownew.obj?


Und es wird noch verwirrender, in VC2003 verwendet MS in einigen Libs das nichtkonforme new() und in einigen die korrekte Form.

The new and delete Operators, Visual Studio .NET 2003

Zitate aus dem Text:

"the CRT's new function (in libc.lib, libcd.lib, libcmt.lib, libcmtd.lib, msvcrt.lib, and msvcrtd.lib) will continue to return NULL if memory allocation fails."

"the new function in the Standard C++ Library (in libcp.lib, libcpd.lib, libcpmt.lib, libcpmtd.lib, msvcprt.lib, and msvcprtd.lib) will support the behavior specified in the C++ standard,"

"Even if you use one of the C++ standard library headers, it is possible to get non-throwing new."

Man muss ab VC2003 mit 'thrownew.obj' linken, um C++ konform zu sein.

??? Was nun, new mit Ex, oder mit == NULL.

Gibt es Warnings vom Compiler?

if( Pointer == NULL ) im Code lassen oder nicht?

Lösung:

Man kann in allen Fällen mit einem eigenen New Handler arbeiten und von Beginn an die Unsauberkeiten umgehen.

Aber wer baut schon einen New Handler ein, wenn man doch seinen aus C gewohnten Stil 'if(pointer==NULL) in C++ beibehalten kann.

"Es geht doch" meint der 'Profi', und schreibt garantiert nicht portablen Code, der irgendwann gegen die Wand rauscht.





Demo Programm zum Verhalten von 'operator new()'

Lizenz: LGPL

GNU Lesser General Public License

Repo bei Github: github: newhandler