new und realloc



  • Hi,

    na, dann ist ja alles klar.
    Wenn Du natürlich auf eine Aussage "new und malloc sollte man nicht mischen" erwiderst "Kann man aber und steht nirgends !" - kann das schon als Aufforderung zum Gegenteil mißverstanden werden.
    Meiner Meinung jedenfalls leichter, als ein "unspecified" im Standard als "klappt meistens" 😉 ....

    Gruß,

    Simon2.



  • ten schrieb:

    firefly schrieb:

    Aber das ändert nichts an der Tatsache, das man malloc und new mischen kann.

    würdest du denn sowas machen?

    char *gimmethatfuckinmemory (int size)
    {
       char *mem = malloc(size);
       if (!mem)
          mem = new char[size];
       return mem;
    }
    

    :p

    oh man ich habe nie behauptet, das ich das mache, sondern nur das es im prinzip geht. Wiso liest hier mancher meine posts nie komplett durch. Habe ich etwa nen Schild umhängen "Lies nur nen teil was ich geschrieben habe und interpretiert dann fröhlich dinge hinzu." ??

    Aber so würde ich es überhaupt net machen, wenn malloc schon nichts bekommt wie sollte den new dann erfolgreicher sein?
    Da ja in der momentan vorhandenen Implementationen malloc und new auf den selben heap zugreifen.



  • Simon2 schrieb:

    Hi,

    na, dann ist ja alles klar.
    Wenn Du natürlich auf eine Aussage "new und malloc sollte man nicht mischen" erwiderst "Kann man aber und steht nirgends !" - kann das schon als Aufforderung zum Gegenteil mißverstanden werden.
    Meiner Meinung jedenfalls leichter, als ein "unspecified" im Standard als "klappt meistens" 😉 ....

    Gruß,

    Simon2.

    Hmm eventuell habe ich mich da etwas ungünstig in meinem 1. post ausgedrückt.
    Aber später habe ich das zumindestens teilweise korrigiert bzw. bewiesen, wie es momentan aussieht in den meistverbreiteten Implementationen von new (bei MS und GNU/Linux mit gcc).



  • firefly schrieb:

    Aber so würde ich es überhaupt net machen, wenn malloc schon nichts bekommt wie sollte den new dann erfolgreicher sein?

    ach ja, das ist ja ein und das selbe 😃
    was hälste denn davon?

    char *mix_it_baby (size_t size)
    {
       if (rand()%2)
          return (char*)malloc(size);
       return new char[size];
    }
    

    :xmas2:



  • ten schrieb:

    firefly schrieb:

    Aber so würde ich es überhaupt net machen, wenn malloc schon nichts bekommt wie sollte den new dann erfolgreicher sein?

    ach ja, das ist ja ein und das selbe 😃
    was hälste denn davon?

    char *mix_it_baby (size_t size)
    {
       if (rand()%2)
          return (char*)malloc(size);
       return new char[size];
    }
    

    :xmas2:

    moep mit dir brauch ich net weiter diskutieren, da du ja eh anscheinent meine posts nie komplett gelesen bzw. teile nicht verstanden hast.



  • firefly schrieb:

    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?

    malloc ist nichts weiter, als eine simple Funktion zur Speicherreservierung. new ist ein "Ausdruck", mit dem man dynamische Objekte erzeugen kann. Du kannst das nicht einfach so in einen Topf hauen. Erkläre mir doch mal, warum trotz deiner Aussage Folgendes unterschiedliches Verhalten hat:

    malloc(sizeof(int))
    new int()
    

    new lässt sich durch malloc vllt. am besten so beschreiben:

    void* p = malloc(sizeof(T));
    new (p) T;
    

    Deshalb ist einfach deine Denkweise falsch, dass "new und malloc gleich sind bis auf...". Das was malloc macht, ist nur ein Teil von dem, was new macht.

    firefly schrieb:

    Also im prinzip kann man malloc und new mischen.

    Du klingst schon fast wie der Leierkastenmann. Vllt. kannst du ja mal erklären, was du uns mit dieser Aussage mitteilen willst. Du kannst in C++ viel machen. Die Frage ist nur, ob es sinnvoll bzw. erlaubt ist. Und malloc und new zu mischen, ist nicht sinnvoll. Also lass es gut sein und versuche hier nicht irgendwas beweisen zu wollen, was überhaupt nicht relevant ist.



  • groovemaster schrieb:

    firefly schrieb:

    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?

    malloc ist nichts weiter, als eine simple Funktion zur Speicherreservierung. new ist ein "Ausdruck", mit dem man dynamische Objekte erzeugen kann. Du kannst das nicht einfach so in einen Topf hauen. Erkläre mir doch mal, warum trotz deiner Aussage Folgendes unterschiedliches Verhalten hat:

    malloc(sizeof(int))
    new int()
    

    new lässt sich durch malloc vllt. am besten so beschreiben:

    void* p = malloc(sizeof(T));
    new (p) T;
    

    Deshalb ist einfach deine Denkweise falsch, dass "new und malloc gleich sind bis auf...". Das was malloc macht, ist nur ein Teil von dem, was new macht.

    firefly schrieb:

    Also im prinzip kann man malloc und new mischen.

    Du klingst schon fast wie der Leierkastenmann. Vllt. kannst du ja mal erklären, was du uns mit dieser Aussage mitteilen willst. Du kannst in C++ viel machen. Die Frage ist nur, ob es sinnvoll bzw. erlaubt ist. Und malloc und new zu mischen, ist nicht sinnvoll. Also lass es gut sein und versuche hier nicht irgendwas beweisen zu wollen, was überhaupt nicht relevant ist.

    öhm ich habe nie behauptet das man das tun soll.
    Und new ist auch "nur eine funktion" welche aber im sprachmittel von C++ integriert wurde.

    Aber du hast meine frage von letzten mal immer noch net beantwortet:

    firefly schrieb:

    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.

    Darauf bist du nicht eingegangen, sondern hackst nur darauf um das ich behaupte, das man new und malloc mischen kann. Aber ich habe immer gesagt, das man es nicht tun soll.

    Wie soll ich dir glauben schenken, wenn du, aus meiner sicht:
    - nur immer auf das selbe rumhackst ohne konkreten beweis, ich habe beweisen, das zumindestens in der Implementation in zwei meist verbreiteten Compilern new indirekt malloc aufruft.
    - manche "fragen" von mir nicht beachtest.
    - anscheinent einfach teile von meinen Posts überlist, denn ich habe immer darauf hingewiesen, das man malloc und new nicht mischen soll.


  • Mod

    firefly schrieb:

    Darauf bist du nicht eingegangen, sondern hackst nur darauf um das ich behaupte, das man new und malloc mischen kann.

    Das liegt am Forum, in dem du postest. In einem anderen compilerspezifischen Forum mag das Thema ein gewisses Interesse hervorrufen. Hier geht es aber zunächst nur um solche Dinge, die dem Sprachstandard selbst zuzuschreiben sind, alles andere ist freigegeben für freie Erörterung 😉



  • camper schrieb:

    firefly schrieb:

    Darauf bist du nicht eingegangen, sondern hackst nur darauf um das ich behaupte, das man new und malloc mischen kann.

    Das liegt am Forum, in dem du postest. In einem anderen compilerspezifischen Forum mag das Thema ein gewisses Interesse hervorrufen. Hier geht es aber zunächst nur um solche Dinge, die dem Sprachstandard selbst zuzuschreiben sind, alles andere ist freigegeben für freie Erörterung 😉

    Mag sein, aber das entschuldigt nicht sein verhalten.



  • firefly schrieb:

    öhm ich habe nie behauptet das man das tun soll.

    Es hat auch niemand behauptet, dass du das behauptet hast. Wie oft willst du denn noch darauf rumreiten?

    firefly schrieb:

    Und new ist auch "nur eine funktion" welche aber im sprachmittel von C++ integriert wurde.

    Liest du dir denn die Beiträge anderer überhaupt durch? new ist keine Funktion, sondern wie ich bereits oben schrieb, ein Ausdruck. Operator new ist eine Funktion und lediglich ein Teil von new. Mittlerweile klinge ich auch schon wie der Leierkastenmann.

    firefly schrieb:

    sondern hackst nur darauf um das ich behaupte, das man new und malloc mischen kann.

    Dann lass es doch einfach bleiben. Niemandem hilft das hier weiter, weil es portabel nicht praktikabel ist. Eine relevante Methode wurde doch mittlerweile mehrfach genannt. Mit solchen Aussagen wie deiner verwirrst du Anfänger nur unnötig, und C++ hat schon mehr als genug Fallen parat.

    firefly schrieb:

    - nur immer auf das selbe rumhackst ohne konkreten beweis, ich habe beweisen, das zumindestens in der Implementation in zwei meist verbreiteten Compilern new indirekt malloc aufruft.

    Wie ich schon sagte, die Referenz in diesem Forum ist der Standard. Wenn du etwas beweisen willst, dann nur anhand dessen. Alles andere ist erstmal bedeutungslos. Aber ich wiederhole mich ja schon wieder. Langsam fange ich an zu glauben, dass du einige grundlegende Verständnisprobleme hast. Was ja ok ist, nur solltest du bereit sein zu lernen. Dafür sehe ich aber bisher keinerlei Ansätze.

    firefly schrieb:

    manche "fragen" von mir nicht beachtest.

    Die da wären? Die einzige konkrete Frage an mich, habe ich auch noch zitiert.

    firefly schrieb:

    - anscheinent einfach teile von meinen Posts überlist, denn ich habe immer darauf hingewiesen, das man malloc und new nicht mischen soll.

    Doch, ich habe deine Beiträge schon gelesen. Deshalb werden sie aber auch nicht glaubwürdiger. Ich kann genauso gut sagen: "... dass man im Prinzip über Arrays hinaus lesend bzw. schreibend zugreifen kann. Nur soll man das nicht machen." Und was ist die Quintessenz des Ganzen? "Lese bzw. schreibe niemals über die Grenzen eines Arrays hinaus!" Alles andere ist bedeutungslos und trägt nichts zur Sache bei. Und das war die Kritik an deinen Aussagen.



  • Frage: Was ist der Unterschied zwischen new und malloc?

    Antwort: "new" ist ein Allocator, "malloc" ein anderer.

    Auf vielen Systemen ruft new zwar bloss malloc auf, auf anderen aber nicht. Man kann und darf ruhig new und malloc "mischen", allerdings nicht "überkreuzen". Also new und dann free oder realloc auf den gleichen Ptr ist Blödsinn, falsch, Mist. In einem Programmteil new/delete und in einem anderen malloc/realloc/free ist dagegen kein Problem.

    Ich weiss echt nicht was es da gross zu diskutieren oder zu erörtern gibt.

    Ist im Prinzip wie die Frage was ist der Unterschied zwischen der Postbank und der Raiffeisenbank. Einen Credit den ich bei der Postbank genommen hab kann ich auch nicht bei der Raiffeisenbank zurückzahlen oder aufstocken lassen. Sollte eigentlich logisch sein...

    Ob es auf dem einen oder anderen System geht, oder sogar auf den meisten, ist dabei vollkommen irrelevant.



  • so um noch mal auf mein ausgangsproblem zurückzukommen, hab ich das jetzt wie folgt gemacht und wollte wissen, ob das so geht bzw ob man das so machen sollte oder nicht.

    class T{...};
    ...
    int _size = 10;
    T** src;
    src = (T**) calloc (_size * sizeof(T));
    if(!src)
      for(int i = 0; i < _size; i++)
      {
        src[i] = new T();
      };
    ...
    

    damit könnte ich dann quasi realloc anwenden um das feld dynamisch zu vergrößern, ohne das feld selber zwischen zu kopieren, und hab gleichzeitig kein 'problem' mit dem konstruktoren. dieser vorschlag wurde übrigens zu beginn schon mal angebracht, glaub ich zumindest. und ich hab ihn jetzt mal umgesetzt.



  • Theoretisch ist das schon so machbar, sofern du lediglich den Speicher hinter src mit realloc vergrösserst, und nicht den hinter src[...].

    Aber warum nimmst du denn nicht einen passenden Container dafür? ZB std::vector. Der bietet ua die Funktionalität, bei Bedarf zu wachsen. Ausserdem sind dort idR Strategien implementiert, dass die Allokationsroutinen so sparsam wie möglich aufgerufen werden, und damit auch ein mögliches Umkopieren reduziert wird. Wenn du jegliches Umkopieren verhindern willst, dann nützt dir auch realloc nichts. Da müsstest du schon von Vornherein die Kapazität so gross wählen, dass dies für jede erdenkliche Situation ausreicht. Ausserdem ist ein Container exception-safe. Mit malloc/free und new/delete können da schnell Ressourcenlöcher entstehen.


  • Mod

    FreakyBKA schrieb:

    so um noch mal auf mein ausgangsproblem zurückzukommen, hab ich das jetzt wie folgt gemacht und wollte wissen, ob das so geht bzw ob man das so machen sollte oder nicht.

    class T{...};
    ...
    int _size = 10;
    T** src;
    src = (T**) calloc (_size * sizeof(T));
    if(!src)
      for(int i = 0; i < _size; i++)
      {
        src[i] = new T();
      };
    ...
    

    damit könnte ich dann quasi realloc anwenden um das feld dynamisch zu vergrößern, ohne das feld selber zwischen zu kopieren, und hab gleichzeitig kein 'problem' mit dem konstruktoren. dieser vorschlag wurde übrigens zu beginn schon mal angebracht, glaub ich zumindest. und ich hab ihn jetzt mal umgesetzt.

    Kann man so machen, wobei allerdings kein plausibler Grund zu sehen ist, warum src mit calloc angefordert wird und nicht ebenfalls mit new. ansonsten siehe groovemasters beiträge.



  • das calloc bzw malloc, hab ich deshalb verwendet um es nachträglich mit realloc vergrößern zu können ohne mir selber das array zwischenzuspeichern, das war doch gegenstand der ganzen diskussionen bisher, ob oder ob man nicht new/delete und malloc/free/realloc mischen sollte. hätte ich das mit new gemacht müsste ich mir selber eine funktion wie realloc halt nur für new schreiben.
    und natürlich trenne ich die dimensionen des arrays, die eine wird nur mit malloc/calloc/free/realloc und die anderen nur mit new/delete behandelt.
    ich habe deshalb keinen container, weil ich mir selbst eine array-klasse schreibe, wie zu anfang schonmal erwähnt.



  • Selbst das kann mächtig in die Hose gehen 😉 realloc() ist afaik nicht verpflichtet, deine Daten an ihrer bisherigen Position stehen zu lassen (ist auch technisch gar nicht machbar) - und dann kopiert er binär und ohne den Copy-Ctor.

    (und wenn du bei einem C++ Objekt am Ctor vorbeiläufst, landest du im weiten Gebiet des undefinierten Verhaltens)



  • ich glaub du hast da was nicht richtig gelesen. es ist nur ein feld mit zeigern auf objekte und nur dieses wird vergrößert, d.h. die objekte an sich bleiben wo sie sind und bei realloc werden nur die zeiger kopiert (falls nötig), demnach brauch ich da keine konstruktoren.


  • Mod

    FreakyBKA schrieb:

    das calloc bzw malloc, hab ich deshalb verwendet um es nachträglich mit realloc vergrößern zu können ohne mir selber das array zwischenzuspeichern, das war doch gegenstand der ganzen diskussionen bisher, ob oder ob man nicht new/delete und malloc/free/realloc mischen sollte. hätte ich das mit new gemacht müsste ich mir selber eine funktion wie realloc halt nur für new schreiben.
    und natürlich trenne ich die dimensionen des arrays, die eine wird nur mit malloc/calloc/free/realloc und die anderen nur mit new/delete behandelt.
    ich habe deshalb keinen container, weil ich mir selbst eine array-klasse schreibe, wie zu anfang schonmal erwähnt.

    Ok, hatte ich mitlerweile vergessen. Wenn realloc verwendet wird, ist es aber sinnvoll, grundsätzlich nur realloc und nie eine der anderen Funktion (malloc/calloc/free) zu benutzen, damit wird die Intention wesentlich deutlicher. Der Begründung durch Bequemlichkeit ist allerdings eigentlich keine, denn wirklich bequem ist ja std::vector. Auch der theoretische Vorteil, dass realloc ohne Kopieren auskommen kann, ist näher besehen eine Fiktion. Entweder tut dein Programm sowieso nicht viel, dann spielt diese eingesparte Zeit keine Rolle. Tut dein Programm dagegen viel (auf dem Heap), dann ist es ohnehin extrem unwahrscheinlich, dass das Kopieren vermieden wird; da realloc keine Garantien (nicht mal im Mittel) gibt, ist diese Einsparung letzlich wertlos.



  • FreakyBKA schrieb:

    ich habe deshalb keinen container, weil ich mir selbst eine array-klasse schreibe, wie zu anfang schonmal erwähnt.

    OK, das ist natürlich was anderes. War mir mittlerweile auch entfallen. Asche auf mein Haupt. :xmas2:
    Dann würde ich aber, ähnlich wie es die stdlib macht, die Allokation/Deallokation von der eigentlichen Klasse separieren. Soweit, dass man im ctor der Array Klasse für den Allokator eine Alternative verwenden kann, muss es ja nicht unbedingt gehen. Damit kannst du dann relativ einfach testen, welche Strategie für Allokation/Deallokation sich für deine Klasse in der Praxis bewährt.
    Ich weiss, diese Idee mit den Zeigern auf die Elemente wurde am Anfang des Threads irgendwann mal gebracht. Grundsätzlich sollte man sowas aber mit Vorsicht geniessen. Selbst für eine Listen Klasse, die für sowas ja nahezu prädestiniert ist, ist das alles andere als optimal. Da kann man zB mit speziellen Allokatoren einiges gut machen. Das Problem ist einfach, dass dynamische Speicherreservierung recht aufwändig sein kann (abhängig von der Implementation). Und das für jedes Element kann je nach Szenario locker weitaus ineffizienter werden, als lineare Speicherreservierung. Zudem müllt es den Speichermanager zu. Ich würde deshalb, zumindest bei einer Array Klasse, eher lineare Speicherreservierung für die Elemente verwenden.



  • irgendwie versteh ich grad nicht so genua worauf du eigentlich hinaus willst.


Anmelden zum Antworten