new und realloc



  • 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.



  • firefly schrieb:

    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.

    Du hast gar nichts bewiesen. Was du machst, nennt man auch "Beweis durch Beispiel", und das funktioniert nicht.

    Von dir/euch kam bis jetz kein wirklicher beweis, das meine Behauptung überhaupt nicht simmt.

    Schreib dir einen eigenen new-Operator, der nicht das gleiche tut wie malloc. Fertig.



  • firefly schrieb:

    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.

    Und wozu soll das gut sein? Niemand hat derartige Beweise verlangt. Zudem bleibt die Referenz der Standard. Wenn du also etwas beweisen willst, dann nur anhand dieses Dokumentes.

    firefly schrieb:

    Von dir/euch kam bis jetz kein wirklicher beweis, das meine Behauptung überhaupt
    nicht simmt.

    Wozu etwas beweisen, was überhaupt nicht relevant ist?

    firefly schrieb:

    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.

    Wenn du schon zitierst, dann bitte richtig. Das habe ich so nie gesagt. Ich sprach von "konkretem Compiler bzw. konkreter Implementation". Und das kann auch mehr als eins sein. Natürlich gibt es Situationen, wo man sich von bestimmten Werkzeugen abhängig macht und dies auch bewusst in Kauf nimmt. Nur sollte man das nicht tun, wenn es nicht nötig ist. Und hier ist es nicht nötig. Wenn du realloc verwenden willst, dann überlade Operator new/delete. So wie es bereits mehrfach gesagt wurde. Dann hast du das Speichermanagement in deiner Hand und fertig.

    firefly schrieb:

    Aber das ganze interessiert eigentlich einen c/c++ programmiere überhauptnicht wie genau new und malloc implementiert ist.

    Das sagt doch schon alles. Und lässt alle anderen Ausführungen deinerseits bedeutungslos werden. Die Implementation interessiert uns nicht. Und deshalb wissen wir auch nichts darüber. Eben eine Black Box. Ob du hier irgendwas beweisen willst, ob dieser oder jener Compiler malloc aufruft, tut überhaupt nichts zur Sache.

    firefly schrieb:

    Wie schon gesagt, man kann malloc und new mischen, solange keine klassen-objekte ins spiel kommen.

    Ich kann auch Nullzeiger dereferenzieren. Oder String Literale beschreiben. Oder über die Grenzen eines Arrays hinaus lesend bzw. schreibend zugreifen. Und was bringt uns das am Ende des Tages? Exakt nichts! Nur kaputte Programme. Die am Anfang vllt. zu funktionieren scheinen. Dir aber spätestens am Tag X sämtliche Rechnerinnereien um die Ohren hauen werden.

    firefly schrieb:

    malloc und new sind bis auf den punkt mit Klassen-objekten nahezu identisch

    Nur noch was kurz dazu, da das auch immer wieder ungenau wiedergegeben wird. Genau genommen sind new und malloc, genauso wie delete und free, zwei verschiedene Sachen. Das C++ Gegenstück zu malloc nennt sich Operator new bzw. zu free Operator delete. Und das ist nur ein Teil von new bzw. delete. Dieser kleine aber feine Unterschied ist wesentlicher Bestandteil des dynamischen Speicherkonzeptes von C++. Die Denkweise muss dementsprechend eher dahin gehen, dass dieser Unterschied für PODs in der Praxis nicht zum Tragen kommt. Und nicht, dass "malloc und new bis auf Klassen-objekte nahezu identisch sind".



  • groovemaster da du anscheinent eh alles besser weist dann sage mir wiso sich new und malloc auser in dem punkt unterscheiden, das bei new der passende Constructor aufgerufen wird wenn man ein Objekt einer Klasse erzeugt?

    Meinem wissen nach, sind malloc und new beides konstrukte/funktionen mit dem man dynamische Speicher bei bedarf vom System anfordern kann.

    Wo genau soll sich denn das dynamische Speicherkonzept von c++ gegenüber c unterscheiden?

    Bei beiden "Funktionen" wird der angeforderte Speicher auf dem heap reserviert.

    Der einzigste unterschied den ich sehe ist der, das bei new dafür gesorgt wird, das bei non-POD Objekten nach dem anfordern des Speichers für das Objekt als solches (ohne den dynamischen anteil),
    eine entsprechende Konstruktions-phase ausgeführt wird (z.b. Aufruf des Constructors bei Klassen-objekten), um dem Objekt zu einem zu ermöglichen sein dynamischen anteil korrekt zu erzeugen und seine Datenmember zu initialisieren.

    Für delete sehe ich das genauso, nur das hier halt vor dem freigeben des Speicherbereiches für das Objekt als solches(ohne dymaischen anteil) eine Destruktions-phase ausgeführt wird, damit das Objekt seinen Dynamischen anteil (falls vorhanden)sauber freigeben kann oder andere "Aufräumarbeiten" noch erledigen kann.

    Wenn es noch andere unterschiede gibt, dann erleuchte einen, aus deiner sicht, unwissenden.



  • firefly schrieb:

    Bei beiden "Funktionen" wird der angeforderte Speicher auf dem heap reserviert.

    es können aber zwei verschiedene heaps sein. wenn vc und gcc den gleichen heap benutzen, hat das garnix zu bedeuten. bereits in der nächsten version kann's anders sein...
    :xmas2:



  • Letztenendes muss so oder so der entsprechende Syscall des jeweiligen Betriebssystem aufgerufen werden. In der Operator new Implementierung malloc aus der libc zu benutzen wäre nur einfacher.

    ten schrieb:

    firefly schrieb:

    Bei beiden "Funktionen" wird der angeforderte Speicher auf dem heap reserviert.

    es können aber zwei verschiedene heaps sein. wenn vc und gcc den gleichen heap benutzen, hat das garnix zu bedeuten. bereits in der nächsten version kann's anders sein...
    :xmas2:

    Häh? Speicherverwaltung macht immer noch der Kernel. Oder welches OS benutzt Du? 😉


Anmelden zum Antworten