realloc C++



  • @unskilled

    Ist memmove aus der C++ standard lib auf ein nicht-trivial-kopierbares objekt UB?

    Laut cppreference: ja!

    Ein char ist trivial kopierbar. Wo ist das Problem?


  • Gesperrt

    @Finnegan sagte in realloc C++:

    Welchen Vorteil hat C, wenn man C++ kann und ein C++-Compiler für die Zielplattform verfügbar ist?

    Den Vorteil, dass man sich nicht über unnötige Abstraktionen den Kopf zerbricht, sondern einfach memmove() oder memcpy() anwendet.



  • @unskilled sagte in realloc C++:

    Ist memmove aus der C++ standard lib auf ein nicht-trivial-kopierbares objekt UB? (Das Problem an der Frage ist natürlich offensichtlich: Jeder kann erst mal ja! sagen, bis dann jemand kommt und sagt "Nein, schaut: ...")

    Alles was der Standard nicht definiert ist undefined-behaviour.

    [class.prop]/1
    [basic.types]/3

    Mehr geht ned.



  • @Finnegan sagte in realloc C++:

    Welchen Vorteil hat C, wenn man C++ kann und ein C++-Compiler für die Zielplattform verfügbar ist?

    C ist schlank und einfach gehalten. ich meine, wir reden hier von mikrocontrollern, da braucht man keine oop.

    welchen vorteil hat C++ denn? class Pin1:Pin? throw PinNotConnectedException? den ganzen kram braucht auf der ebene doch kein mensch! wahrscheinlich brauchst du da nicht mal realloc, weil du direkt in den speicher schreiben kannst bzw. gar keine speicherverwaltung vorhanden ist.

    C++ löst probleme, die man ohne C++ gar nicht hätte, oder wie war das?



  • @Wade1234 sagte in realloc C++:

    C++ löst probleme, die man ohne C++ gar nicht hätte, oder wie war das?

    Auf Mikrocontrollerebene gebe ich dir Recht. Da ist C++ im Grunde unnötig, aber dort baut man auch keine riesen Projekte.
    Bei großen Softwareprojekten wirst du mit C ne ganze Menge mehr Aufwand haben als mit C++.



  • @RBS2, @Wade1234 Trollt euch doch bitte mit euren Privatmeinungen aus C++-Threads. Nach einer Entscheidungshilfe bei einer Sprachenwahl hat hier niemand gefragt.



  • @It0101 sagte in realloc C++:

    Auf Mikrocontrollerebene gebe ich dir Recht. Da ist C++ im Grunde unnötig, aber dort baut man auch keine riesen Projekte.

    und genau darum gehts doch:
    @unskilled sagte in realloc C++:

    Ich beschäftige mich gerade mit Mikro-Controllern und somit ist Speicher jeder Art sowie nutzbare Bibliothek sehr stark begrenzt.

    @Swordfish sagte in realloc C++:

    @RBS2, @Wade1234 Trollt euch doch bitte mit euren Privatmeinungen aus C++-Threads. Nach einer Entscheidungshilfe bei einer Sprachenwahl hat hier niemand gefragt.

    ja das ist wohl am besten so.🙄



  • @unskilled Im aktuellen C++ Standard gibt es dazu schlicht und ergreifend nix brauchbares. Dinge die in diese Richtung gehen (Traits ala "is-memcpy-relocatable" oder "is-trivially-relocatable") werden AFAIK aktuell diskutiert, aber geben tut's sie halt noch nicht.



  • Das relocatable-Problem haben auch schon andere erkannt. In Facebooks vector-Ersatz folly::fbvector muss man einen Typ mit einem IsRelocateable-Trait markieren. Siehe https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md#object-relocation.

    Wäre schön, wenn man dem std::vector sowas beibringen könnte.



  • @Wade1234 sagte in realloc C++:

    @It0101 sagte in realloc C++:

    Auf Mikrocontrollerebene gebe ich dir Recht. Da ist C++ im Grunde unnötig, aber dort baut man auch keine riesen Projekte.

    und genau darum gehts doch:
    @unskilled sagte in realloc C++:

    Ich beschäftige mich gerade mit Mikro-Controllern und somit ist Speicher jeder Art sowie nutzbare Bibliothek sehr stark begrenzt.

    Warum ist der Thread dann im C++-Forum und nicht im C-Forum? Der Verdacht drängt sich mir auf, dass hier Schlamperei-Mischmasch betrieben werden soll.



  • @It0101 sagte in realloc C++:

    Warum ist der Thread dann im C++-Forum und nicht im C-Forum? Der Verdacht drängt sich mir auf, dass hier Schlamperei-Mischmasch betrieben werden soll.

    diesen verdacht hatte ich auch und genau das war auch der grund, weshalb ich so doof gefragt habe, warum kein C verwendet werden soll. die antwort habe ich ja auch bekommen:

    @unskilled sagte in realloc C++:

    C benutze ich nicht, weil zu wenig Ahnung und zu faul was neues zu lernen^^



  • @Wade1234 sagte in realloc C++:

    @unskilled sagte in realloc C++:

    C benutze ich nicht, weil zu wenig Ahnung und zu faul was neues zu lernen^^

    Ja gut.... dazu fällt mir dann nicht mehr all zu viel ein. Wenn man nie Auto-Fahren gelernt hat und es nicht lernen will, dann sollte man es eigentlich lassen, weil andernfalls zuviele Unfälle passieren.



  • @wob sagte in realloc C++:

    Das relocatable-Problem haben auch schon andere erkannt. In Facebooks vector-Ersatz folly::fbvector muss man einen Typ mit einem IsRelocateable-Trait markieren. Siehe https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md#object-relocation.

    Danke, genau danach hab ich ja gefragt 🙂
    Offenbar finden die auch keine bessere Definition, als die beiden Ausnahmen anzuführen^^

    @It0101 sagte in realloc C++:

    Warum ist der Thread dann im C++-Forum und nicht im C-Forum? Der Verdacht drängt sich mir auf, dass hier Schlamperei-Mischmasch betrieben werden soll.

    Weil ich es nun mal für C++ wissen wollte. Irgendwie ist die Funktion ja auch Teil des C++ Standards.
    Aber schön zu wissen, dass sich in den letzten Jahren nichts an den Antworten geändert hat. Selbst wenn ich explizit im ersten Post schreibe, dass ich das wissen möchte, sind die Hälfte der Antworten völlig am Thema vorbei...

    Hier nen relativ interessanter Thread dazu
    https://stackoverflow.com/questions/29777492/why-would-the-behavior-of-stdmemcpy-be-undefined-for-objects-that-are-not-triv

    Und einer mit einer schönen Zusammenfassung:
    https://stackoverflow.com/questions/39026871/can-i-use-memcpy-to-write-to-multiple-adjacent-standard-layout-sub-objects

    In the example, the three members comprise a "trivially copyable sub-object", and indeed I think wrapping them in an actual subobject of distinct type would still mandate exactly the same memory layout for the explicit object as for the three members:

    [...]

    • have a very, very hard time imagining an implementation or optimizer that breaks this

    Would say it either can be:

    • read as Undefined Behavior, iff we conclude that C++§3.9/3 implies that only (full) objects of Trivially Copyable Type are allowed to be be treated thusly by memcpy or conclude from C99§6.2.6.1/2 and the general spec of memcpy 7.21.2.1 that the contiguous sequence of the num_* bytes does not comprise a "valid object" for the purposes of memcopy.

    • read as Defined Behavior, iff we conclude that C++§3.9/3 does not normatively limit the applicability of memcpy to other types or memory ranges and conclude that the definition of memcpy (and the "object term") in the C99 Standard allows to treat adjacent variables as a single object contiguous bytes target.

    @andere Mutmaßungen wie Exceptions auf µCtrl oder das Auto fahren werde ich mal versuchen zu ignorieren.



  • @Wade1234 sagte in realloc C++:

    diesen verdacht hatte ich auch und genau das war auch der grund, weshalb ich so doof gefragt habe, warum kein C verwendet werden soll. die antwort habe ich ja auch bekommen:

    Warum sollte man C verwenden wollen?
    Es gibt auch auf Microcontroller gute Gründe C++ einzusetzen.

    • Der erzeugte Code ist faktisch gleich groß.
    • C++ ist strenger typisiert.
    • Templates helfen massenweise Fehler mit C Makros zu verhindern, da Templates typsicher sind.

    Es gibt dazu auf youtube von den diversen C++ Meetings Vorträge zum Anschauen.



  • @unskilled sagte in realloc C++:

    die (vermutlich gar nicht so dumme) alternative wäre wohl nen eigener allocator, der einfach (fast) alles am reserviert und selbst was realloc-mäßiges anbietet. das sieht aber recht schnell recht hässlich im quellcode aus (alloc überall rumreichen). Und hat wieder nen overhead. Wäre aber vom Lerneffekt und den Möglichkeiten her sicher am coolsten.

    Mit dem Overhead bin ich mir nicht so sicher, schliesslich unterstützt auch std::vector einen nutzerdefinierten Allocator. Dieser sollte eigentlich, sofern kein polymorphic_allocator verwendet wird, lediglich über den Allocator-Typ gegeben sein, der Teil des vector-Typs ist, also keinen zuzätzlichen Daten-Member benötigen. Auch würde ich davon ausgehen, dass zumindest der Standard-Allocator so leichtgewichtig implementiert ist, dass die Allokationen unter Compiler-Optimierungen zu direkten malloc/free-Aufrufen mit der richtigen Anzahl von Bytes zerfallen (obwohl ich mir das noch nicht direkt im Maschinencode angesehen habe).

    Ein eigener Allocator kann aber relativ schnell ziemlich komplex werden, daher ein anderer Vorschlag:

    Wie wäre es, wenn dein Vector zur Compile-Zeit erkennt, ob eine malloc-Implementation verwendet wird, die ein flexibleres reallocunterstützt. Du kannst den speziellen reallocate-Code dann für ausgewählte Implementationen unterstützen, z.B. indem du in diesem Fall dann auf realloc2 von nedmalloc oder auf _expand von Visual C++ (https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/expand?view=vs-2017) zurückgreifst. Für unterstütze Allokatoren kannst du dann einen effizienteren Code anbieten.

    @Finnegan

    Welchen Vorteil hat C, wenn man C++ kann und ein C++-Compiler für die Zielplattform verfügbar ist?

    Na der Vorteil liegt auf der Hand: Ich wüsste zweifelsohne, dass memmove wohl definiert ist (in C ist es das auf struct foo von oben). Aber mir persönlich ist da RAII zu viel wert.

    Dieser scheinbare Vorteil trügt. In C++ ist memmove für exakt die selben Objekt-Kategorien (POD) wie in C "wohl definiert". In dieser Hinsicht kann C++ nicht "weniger" als C.

    Also zurück zur Frage:
    Ist memmove aus der C++ standard lib auf ein nicht-trivial-kopierbares objekt UB? (Das Problem an der Frage ist natürlich offensichtlich: Jeder kann erst mal ja! sagen, bis dann jemand kommt und sagt "Nein, schaut: ...")
    Oder ist nur UB, was danach herauskommt? (T(old_mem) != T(new_mem))
    Oder (und?) ist das beides "[praktisch] well formed"?
    Oder ist es immer well formed; abgesehen davon, dass das neue Objekt eben Invarianz hervorrufen kann?

    Das Problem mit dem UB ist, dass es wahrscheinlich funktioniert, wenn man Klassen manuell als memmove-sicher markiert (siehe auch Beitrag von wob), theoretisch darf aber Compiler deinen Code so verändern, als würde dieser UB-Fall nicht eintreten. Er darf z.B. die memmove-Aufrufe für solche Typen komplett herausoptimieren. Ohne eine eigene Speicherverwaltung, oder eine spezifische mit flexiblem realloc, wie eben nedmalloc oder andere, wirst du also wohl oder übel mit dem UB leben müssen. Sowas kann man durchaus machen, es gibt jede Menge Code der sich auf ein spezielles Verhalten des Compilers bei UB verlässt (und nicht immer unbeabsichtigt). Man muss sich halt immer bewusst sein, dass es eben nicht standardkonform ist und vom Wohlwollen des jeweiligen Compilers abhängt.

    Mit dem UB leben und es wie folly::fbvector zu machen ist also die andere, wesentlich schneller umzusetzende Lösung (vs. eigener/vorgegebener Allocator).



  • @john-0 sagte in realloc C++:

    Warum sollte man C verwenden wollen?

    gegenfrage: warum sollte man eine funktion verwenden wollen, die eigentlich nur deshalb teil von c++ ist, weil c++ vor vielen jahren mal sowas wie "c mit erweiterungen" war?

    Es gibt dazu auf youtube von den diversen C++ Meetings Vorträge zum Anschauen.

    es gibt auf youtube auch garantiert vorträge zum anschauen, warum persil besser wäscht als ariel.



  • @Wade1234 sagte in realloc C++:

    gegenfrage: warum sollte man eine funktion verwenden wollen, die eigentlich nur deshalb teil von c++ ist, weil c++ vor vielen jahren mal sowas wie "c mit erweiterungen" war?

    Weshalb muss man hier im Forum immer wieder sinnfreie Grundsatzdiskussionen führen, wenn man etwas machen will/muss, was nicht den üblichen Gepflogenheiten in C++ entspricht? Es gibt auch für diese Sonderfälle gute Gründe. Also, ist es sinnvoll C++ für Microcontroller zu verwenden – ja. Ist die gestellte Frage in diesem Kontext sinnvoll – ja. Weshalb also das viele Rauschen im Thread?



  • ja ihr macht das schon alle......



  • @Finnegan sagte in realloc C++:

    @unskilled sagte in realloc C++:

    die (vermutlich gar nicht so dumme) alternative wäre wohl nen eigener allocator, der einfach (fast) alles am reserviert und selbst was realloc-mäßiges anbietet. das sieht aber recht schnell recht hässlich im quellcode aus (alloc überall rumreichen). Und hat wieder nen overhead. Wäre aber vom Lerneffekt und den Möglichkeiten her sicher am coolsten.

    Mit dem Overhead bin ich mir nicht so sicher, schliesslich unterstützt auch std::vector einen nutzerdefinierten Allocator. Dieser sollte eigentlich, sofern kein polymorphic_allocator verwendet wird, lediglich über den Allocator-Typ gegeben sein, der Teil des vector-Typs ist, also keinen zuzätzlichen Daten-Member benötigen. Auch würde ich davon ausgehen, dass zumindest der Standard-Allocator so leichtgewichtig implementiert ist, dass die Allokationen unter Compiler-Optimierungen zu direkten malloc/free-Aufrufen mit der richtigen Anzahl von Bytes zerfallen (obwohl ich mir das noch nicht direkt im Maschinencode angesehen habe).

    Na nur einen Standard-Allok. zu schreiben, der free/malloc/realloc aufruft meinte ich nicht. So mache ich es ja jetzt und wollte eben ein sinnvolles kriterium für irgendetwas is_relocatable-mäßiges haben. Die Lösung vom fb-vektor finde ich verhältnismäßig hübsch und elegant.

    Ich hatte von ner eigenen speicherverwaltung im allokator geredet. ein memory-pool halt; kein allokator im eigentlichen sinne.

    Dieser scheinbare Vorteil trügt. In C++ ist memmove für exakt die selben Objekt-Kategorien (POD) wie in C "wohl definiert". In dieser Hinsicht kann C++ nicht "weniger" als C.

    Naja - in C hätte man das Problem nicht, weil es ja ein trivial zu kopierender Typ wäre und die funktionen zum manipulieren der Daten außerhalb sind und nicht so versteckt aufgerufen werden können.

    Das Problem mit dem UB ist, dass es wahrscheinlich funktioniert, wenn man Klassen manuell als memmove-sicher markiert (siehe auch Beitrag von wob), theoretisch darf aber Compiler deinen Code so verändern, als würde dieser UB-Fall nicht eintreten. Er darf z.B. die memmove-Aufrufe für solche Typen komplett herausoptimieren. Ohne eine eigene Speicherverwaltung, oder eine spezifische mit flexiblem realloc, wie eben nedmalloc oder andere, wirst du also wohl oder übel mit dem UB leben müssen. Sowas kann man durchaus machen, es gibt jede Menge Code der sich auf ein spezielles Verhalten des Compilers bei UB verlässt (und nicht immer unbeabsichtigt). Man muss sich halt immer bewusst sein, dass es eben nicht standardkonform ist und vom Wohlwollen des jeweiligen Compilers abhängt.

    Deshalb hatte ich noch den 2. Thread verlinkt und zitiert.

    Also unterm Strich und als Zusammenfassung:
    is_relocatable habe ich vom FBvector abgeguckt.
    Meine Container rufen ein allocator::reallocate auf und der ruft entweder ::realloc auf oder eben allocate std::uninitialized_copy* und deallocate.
    Damit habe ich UB, wenn der Klassen-Schreiber das für nötig hält (relocatable spezialisierung) und ansonsten ist's standard-konform.

    1*
    alternativ dazu etwas uninitialized_swap-mäßiges oder doch nur N x {placement_new + destroy}.
    Da hab ich mich noch nicht entschieden.


  • Gesperrt

    @john-0 sagte in realloc C++:

    Also, ist es sinnvoll C++ für Microcontroller zu verwenden – ja.

    Zumindest seit es Microcontroller gibt, die über mehrere MB RAM und Flash verfügen. Aber darauf nutzt man dann doch lieber VM-Sprachen, die einen GC, JIT-Compilierung und eine fette Laufzeitumgebung haben. 🐱


Anmelden zum Antworten