new und realloc
-
FreakyBKA schrieb:
das heißt wenn ich mit objekten arbeite, sollte ich immer mit new arbeiten, damit die konstruktoren etc. richtig abgearbeitet werden?
so isses, dann fühlt sich c++ am wohlsten. bei malloc müssteste den konstruktor irgendwie manuell starten. ich würde sowas lieber lassen...
:xmas2:ss schrieb:
Da new indirekt malloc aufruft kann man im prinzip das schon mischen.
nö, im prinzip *nicht*
-
ten schrieb:
FreakyBKA schrieb:
das heißt wenn ich mit objekten arbeite, sollte ich immer mit new arbeiten, damit die konstruktoren etc. richtig abgearbeitet werden?
so isses, dann fühlt sich c++ am wohlsten. bei malloc müssteste den konstruktor irgendwie manuell starten. ich würde sowas lieber lassen...
:xmas2:ss schrieb:
Da new indirekt malloc aufruft kann man im prinzip das schon mischen.
nö, im prinzip *nicht*
doch schon
habs selbst getestet
aber wie ich und andere schon geschrieben haben funktioniert das aber nur mit nicht klassen-objekten. Und es kann zu laufzeit problemen führen.In welcher weise sollte sich das verhalten von malloc und new denn noch unterscheiden auser dem punkt mit dem aufrufen des Konstruktors bei klassen-objekten?
Ich habe gerade in den sourcen von gcc nachgeschaut: und da wird bei dem new-operator malloc aufgerufen um den eigentlichen Speicher zu reservieren.
-
ss schrieb:
doch schon
habs selbst getestet 
Im Standard ist trotzdem nicht festgelegt, dass Operator new malloc aufruft. Insofern kann eine Implementation das handhaben, wie sie will. Daher ist es einfach ungesund new/delete und malloc/free zu vermischen. Wie deine Implementation das macht, ist deshalb relativ belanglos.
-
Seine Implementation?
g++ ist ja wohl der mit Abstand meistverwendete C++ - Compiler in der Unixwelt.
-
Was an groovemasters Aussage exakt nichts ändert.
-
Hätte ich nie behauptet.
-
AFAIK kann man doch new überschreiben. Und ich glaube man kann es auch so überschreiben, dass man angeben kann, wo das Objekt erstellt werden soll. D.h. man könnte dann den Array-Speicher mittels realloc vergrößern und das neue Objekt mit dem überschriebenen new auf dem Speicher anlegen.
Allerdings ist das gefährlich wenn ein Objekt z.B. seinen this-Zeiger als mem-var speichert (oder sonstwas).
Das beste für ein (selbstgemachtes) Array für Klassen ist IMO, ein Array von Zeigern mit malloc/realloc/free zu verwalten, welche auf die Objekte zeigen. Das dürfte std::vector aber wahrscheinlich auch so machen
-
das mit den array von zeigern ist auch keine schlechte idee, werde ich wohl dann mal so probieren.
aber mal ne andere frage, woher weiß realloc eigentlich wie groß mein übergebenes feld ist, die funktion bekommt ja nur den zeiger und die neue größe als parameter. das heißt es muss dann irgendwie im speicher eine bestimmte codierung geben die mir sagt hier ist das array zu ende. dann stell ich mir aber die frage was passiert wenn ich in meinem aktuellen array an einer stelle diese codierung reinschreibe und dann realloc aufrufe.
kann mir vllt jemand erklären wie genau das geregelt ist. danke schonmal im voraus.
-
FreakyBKA schrieb:
...woher weiß realloc eigentlich wie groß mein übergebenes feld ist, ...
kann mir vllt jemand erklären wie genau das geregelt ist. danke schonmal im voraus.Soweit ich weiß, ist das überhaupt nicht "geregelt" ... das kann eine konkrete runtime-Implementation machen, wie sie will. .. Trifft übrigens auf free ebenso zu: "Irgendwo im System" hinterlegt malloc(), wie viel Speicher es für diesen Pointer alloziert hat ... und dort rufen es free(), realloc() & Co dann ab.
Gruß,
Simon2.
-
das wird dann bei new und delete wohl ganz ähnlich sein. wenn ich mir dann jetz für objektfelder die ich mit new erstellt habe ein funktion wie realloc(), halt nur für new zB. renew(), schreibe muss ich der funktionen den zeiger auf das alte feld, die alte größe und die neue größe übergeben. die alte größe brauch ich ja dann um das alte feld zwischenzuspeichern. wenn die alte feldgröße vom benutzer eingegeben wird kann man dann doch aber sicherlich ziemlich viel blödsinn mit anstellen, wenn ich mein feld als größer angebe als es eigentlich war. ich habs schon mit kleinen feldern ausprobiert und es funktioniert, ich konnte sogar den inhalt von speicherplatz, den ich gar nicht alloziert habe ändern, was ich sehr bedenklich finde.
-
Simon2 schrieb:
das kann eine konkrete runtime-Implementation machen, wie sie will. .. Trifft übrigens auf free ebenso zu: "Irgendwo im System" hinterlegt malloc(), wie viel Speicher es für diesen Pointer alloziert hat ... und dort rufen es free(), realloc() & Co dann ab.
oft basieren heaps auf verketteten listen und diese informationen stehen oft direkt vor dem speicherblock den man gemalloct hat. z.b da:
int *m = malloc(100); struct block_info *info = (struct block_info*)((char*)m)-sizeof(struct block_info);ab da man als normaler c/c++ user diese struktur nicht kennt und weil's sowieso 'implementation-defined' ist, kann man's nicht verwerten...
:xmas2:
-
OK im standard steht nicht drinn das der new-operator intern malloc/calloc/realloc aufrufen muss aber es steht da auch nicht drinn, das dies verboten sei.
Sprich die wahl ob malloc oder eine neuimplementation der Speicherreservierungs-algo verwendet wird kann der Compiler-/c++-Runtime entwickler selbst entscheiden.aus http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf seite 401:
void * operator new(std :: size_t size ) throw (std :: bad_alloc );
1 Effects:The allocation function (3.7.3.1) called by a new-expression (5.3.4) to allocate size bytes of storage
suitably aligned to represent any object of that size.
2 Replaceable: a C++ program may define a function with this function signature that displaces the default version
defined by the C++ Standard library.
3 Required behavior: Return a non-null pointer to suitably aligned storage (3.7.3), or else throw a bad_alloc
exception. This requirement is binding on a replacement version of this function.
4 Default behavior:
— Executes a loop: Within the loop, the function first attempts to allocate the requested storage. Whether the
attempt involves a call to the Standard C library function malloc is unspecified.Die Verwendung von malloc in der implementation von new ist in der hinsicht sinnvoll, da man dadurch code-duplication vermeiden kann.
Desweiteren muss man nicht auch noch den new-operator reimplemntieren, wenn man die c- und die c++ Runtime/Compiler auf eine neues Betriebsystem/neue Architektur portiert, wo sich das Memory-Management eventuell anders verhält/aufgebaut ist.
ich(ich bin ss, da ich bisher zu faul war mich einzuloggen ;)) habe aber immer darauf hingewiesen, das man malloc und new nicht mischen sollte. Ich habe nur gesagt, das es im prinzip geht und nicht gesagt das man das tun soll.
Und ich konnte meine Behauptung, das new indirekt malloc aufruft auch beweisen(zumindestens in der implementation vom gcc-projekt)
-
firefly schrieb:
Und ich konnte meine Behauptung, das new indirekt malloc aufruft auch beweisen(zumindestens in der implementation vom gcc-projekt)
Wir programmieren aber nicht für einen konkrete Compiler bzw. eine konkrete Implementation, sondern wollen so portabel wie möglich bleiben. Und da interessiert es einfach nicht, was GCC hier macht. Zumal die Möglichkeit besteht, dass sich die Implementation von new/delete in späteren Versionen des GCC ändern könnte.
-
Wenn du mit malloc oder realloc den Speicher holst, kannst du die Größe mit _msize holen. Müsste eigentlich immer konform sein...
-
Badestrand schrieb:
Wenn du mit malloc oder realloc den Speicher holst, kannst du die Größe mit _msize holen. Müsste eigentlich immer konform sein...
ich glaub' _msize gibt's nur bei mickrigsoft und steht nicht in der c oder c++ spec.
:xmas2:
-
d.h. wenn ich einen zeiger ptr habe bekomme ich mit _msize(ptr) die größe des allozierten speichers? ist das dann die feldgröße oder muss ich dann noch durch sizeof(typ) dividieren um meine feldgröße zubekommen? die frage ist dann noch ob es dieses _msize() überall gibt.
-
FreakyBKA schrieb:
die frage ist dann noch ob es dieses _msize() überall gibt.
die frage ist, ob du mit aller gewalt plattformunabhängig coden willst

:xmas2:
-
FreakyBKA schrieb:
die frage ist dann noch ob es dieses _msize() überall gibt.
Nein. Deshalb, merk dir die Grösse. Oder verwende einen passenden Container, der das für dich macht. Bequemer geht's nicht. Speicherverwaltung sollte kein primäres Aufgabengebiet eines Entwicklers sein.
-
groovemaster schrieb:
firefly schrieb:
Und ich konnte meine Behauptung, das new indirekt malloc aufruft auch beweisen(zumindestens in der implementation vom gcc-projekt)
Wir programmieren aber nicht für einen konkrete Compiler bzw. eine konkrete Implementation, sondern wollen so portabel wie möglich bleiben. Und da interessiert es einfach nicht, was GCC hier macht. Zumal die Möglichkeit besteht, dass sich die Implementation von new/delete in späteren Versionen des GCC ändern könnte.
öhm die MS-CRT macht das fast genause(vorrausgesetzt die beim MSVC++2005 mitgelieferten sourcen von der crt entsprechend dem code von der compilierten Fassung).
Ok der new operator ruft da nicht direkt malloc auf aber _heap_alloc. Aber malloc ruft intern auch heap_alloc auf -> malloc und new sind bis auf den punkt mit Klassen-objekten nahezu identisch.
Ich habe dir nun bewiesen, anhand der implementationen von 2 großen Compiler Hersteller, das new indirekt malloc(beim MSCRT ist das die funktion _heap_alloc) aufruft.
Aber ich wiederhole mich nocheinmal ich habe nie behauptet, das man malloc und new mischen soll. Ich habe nur behauptet, das dies möglich ist(wenn auch nur für nicht Klassen Objekten) und das new indirekt(im prinzip) malloc aufruft um den eigentlichen Speicher zu reservieren.
Und ich vermute, das dies für die anderen c++-compiler/-runtimes auch gilt.
Von dir/euch kam bis jetz kein wirklicher beweis, das meine Behauptung überhaupt
nicht simmt.Und groovemaster da anscheinent die MSCRT das auch so macht, ist dein argument, "das wir nicht für einen einzigen Compiler entwickeln" auch nicht haltbar.
Aber das ganze interessiert eigentlich einen c/c++ programmiere überhauptnicht wie genau new und malloc implementiert ist.
Wie schon gesagt, man kann malloc und new mischen, solange keine klassen-objekte ins spiel kommen. Aber dieses mischen kann mit hoher sicherheit zu laufzeit problemen führen. Ergo sowas sollte man nicht machen.
-
firefly schrieb:
...ich vermute, das dies für die anderen c++-compiler/-runtimes auch gilt....
... und es bleibt dabei, dass jeder selbst entscheiden muß, ob er sich auf eine einzelne Vermutung, die er im Internet findet verlassen möchte ... oder lieber auf ddas "geschrieben Wort des Standards".

Gruß,
Simon2.