Typ size_t beim Überschreiben von new



  • 314159265358979 schrieb:

    Wäre im C++ Standard eine exakte Größe für Datentypen festgelegt, dann wird der Code auf bestimmten Mikroprozessoren nicht laufen.

    Das musst du mir erklären.

    Ich sehe es genau umgedreht, wenn der Datentyp den ich gewählt habe mit einmal kleiner ist, dann läuft mein Programm auf der Architektur nicht mehr. Wären die Datentypen genau spezifiziert, gäbe es solche Probleme nicht (und wozu haabn C/C++ eigentlich mehrere Datentypen für den selben Zahlenbereich?).

    Es wäre viel besser wenn es für jeden Zahlenbereich genau einen Typen geben würde und der wäre genau festgelegt, da gäbe es dann keine Gründe warum man mit sowas aufpassen muss wenn ein Programm z.B. von 32bit auf 64bit portiert wird!

    314159265358979 schrieb:

    Du darfst eben nicht beide Sprachen als PC-Only Sprachen sehen, wie das z.B. bei Java der Fall ist. C/C++ ist mehr.

    Wieso sollt Java PC-only sein? Java läuft auf jeder Architektur wo man ne VM dafür hat (und ich möchte meinen auch schon was von Java auf Mikrokontroller gehört zu haben).

    314159265358979 schrieb:

    Habe ich z.B. noch nie gebraucht. Aber stell dir vor, das gibts bereits.

    Aber irgendjemand muss ja die Library schreiben. Zumal damit die "Standard"-Libraries nicht Compiler unabhängig sind (ohne die ifdef´s).

    Aber keiner konnte mir nun sagen wer recht hat (bezüglich welchen Typ von Parameter new erwartet) clang oder gcc?



  • FlashBurn schrieb:

    Aber keiner konnte mir nun sagen wer recht hat (bezüglich welchen Typ von Parameter new erwartet) clang oder gcc?

    Ähm, size_t und clang und gcc widersprechen sich dahingehend gar nicht?



  • Der Compilerbauer entscheidet selbst, welchen Typ operator new erwartet. Den musst du aber nicht wissen. Um platformunabhängigr Programme zu ermöglichen ist genau für diesen Typ ein typedef standardisiert: size_t .

    Die Intension, für die Standardtypen keine festen Größen vorzuschreiben, hat übrigens Performancegründe. So sollte int ursprünglich genau ein Maschienenregister groß sein, so dass es also Mittel der Wahl ist, wenn man im beschränkten Wertebereich optimal schnell rechnen will. Braucht man feste Größen gibt es immer noch int32_t , int32_least_t , int32_fast_t etc. Leider haben sich im Laufe der Zeit so viele Programmierer und Programme an sizeof(int) == 4 gewöhnt, das man aus Gründen der Abwärtskompatibilität unter x64 int nicht einfach auf 8 Byte setzen konnte.



  • @volkard

    Aber size_t ist unterschiedlich definiert und das dürfte ja eigentlich auch nicht sein, oder?

    Ich sags mal so, entweder ist der Standard nicht eindeutig genug oder die Compiler-Bauer machen mal wieder was sie wollen 😉

    Edit::

    @ipsec

    Den Typ den new erwartet muss ich spätestens dann wissen, wenn ich die Standard-Library auf eine andere Plattform portiere und/oder eine Compiler unabhängige Standard-Library schreiben will (gibt sicherlich noch mehr Gründe).



  • FlashBurn schrieb:

    @volkard
    Aber size_t ist unterschiedlich definiert und das dürfte ja eigentlich auch nicht sein, oder?

    Doch, das darf sein. Es ist absolut ok. In der Praxis gibt es keine Probleme damit. Es gibt nur Probleme, wenn man erwartet, daß size_t genau 4 Bytes hat und dann beim Compilerwechsel überrascht ist.
    Und natürlich, wenn man den ganzen Videofilm mit 3.7GB in einen std::vector stopfen will, was bei sizeof(size_t)==4 nicht klappen wird.



  • FlashBurn schrieb:

    Ich sags mal so, entweder ist der Standard nicht eindeutig genug oder die Compiler-Bauer machen mal wieder was sie wollen 😉

    It's not a bug. It's a feature.
    Der C++-Standard läßt ganz viele Sachen offen. Und allermeistens sogar mit voller Absicht.



  • FlashBurn schrieb:

    @volkard

    Aber size_t ist unterschiedlich definiert und das dürfte ja eigentlich auch nicht sein, oder?

    Ich sags mal so, entweder ist der Standard nicht eindeutig genug oder die Compiler-Bauer machen mal wieder was sie wollen 😉

    Nicht die Compiler-Bauer, sondern die CPU-Bauer 😉 size_t ist so definiert, daß er auf deiner Zielplattform jede plausible Größenangabe aufnehmen kann, die das System hergibt.

    Den Typ den new erwartet muss ich spätestens dann wissen, wenn ich die Standard-Library auf eine andere Plattform portiere und/oder eine Compiler unabhängige Standard-Library schreiben will (gibt sicherlich noch mehr Gründe).

    Auf Quellcode-Ebene kannst du eine ANSI-konforme Library überall hinportieren, wo du einen vernünftigen C++ Compiler zur Verfügung hast. Auf Binär-Ebene hast du vermutlich ganz andere Probleme, weil Plattform 1 womöglich nichts mit dem Maschinencode anfangen kann, den du für Plattform 2 erzeugt hast.

    Und welchen Typ new erwartet, ist im Standard genau festgelegt - es ist *trommelwirbel* size_t



  • volkard schrieb:

    In der Praxis gibt es keine Probleme damit.

    Nur wenn ich das weiß und size_t entsprechend mit ifdef´s für den jeweiligen Compiler definiere.

    Als Bsp. sei mal ein Kernel genannt, ich werde bei einem Kernel nicht die Standard-Library vom Compiler nehmen (kann ich ohnehin nicht, jedenfalls nicht so einfach), sondern entweder meine eigene schreiben oder nur das schreiben, was ich brauche (oder halt entsprechend anpassen).

    Sicherlich bindet man sich gerade mit nem Kernel doch sehr stark an den Compiler, aber wenn du ihn wechselst und mit einmal feststellen musst, das der Kernel nicht mehr läuft oder kompiliert werden kann, weil die Typen nicht eindeutig definiert sind, sehe ich das als failure-by-design an.

    Anderes Bsp. wären Mikrokontroller. Ich will dort auch new nutzen (als Bsp.) und dort nehme ich bestimmt keine Standard-Library sondern, werde eigenen Code nutzen und muss wieder aufpassen was der Compiler nun erwartet.

    Das sind Probleme die man vllt nicht auf der PC-Plattform hat, aber wenn man mal über den Tellerrand guckt, wird man feststellen, dass es einige solcher Probleme gibt und eigentlich wurden C und C++ doch genau damit angepriesen das sie Plattform/Hardware unabhängig seien.



  • Hab ich doch mit

    typedef decltype(sizeof(0)) Size;
    

    längst gelöst. Sogar zufällig ohne #ifdef. Und rede nicht vom Tellerrand.



  • Wenn du für einen Microcontroller programmierst, sollte dein Compiler schon eine portierte Standardlibrary anbieten. Und bei der Betriebssystemprogrammierung kannst du durchaus die Standardbibliothek verwenden. Bestimmte Dinge wie Speicherverwaltung usw. musst du zwar selbst implementieren (die Standardlibraryentwickler können ja nicht wissen, wie du das gerne hättest), aber es geht.

    Ich sehe auch dein Problem nicht. Systeme sind unterschiedlich und erfordern unterschiedlichen Code. Das man trotzdem mit C++ platformunabhängig programmieren kann, liegt daran, weil die Bibliotheken, allen voran die Standardbibliothek, für die verschiedenen Systeme portiert sind und systemabhängige Funktionen unter einem einheitlichen Interface kapseln.
    Bei Java muss eben für jedes System die JVM portiert werden, bei C++ die Standardbibliothek. Das hat nichts mit Failure-by-Design zu tun.



  • volkard schrieb:

    Hab ich doch mit ...

    Das muss ich irgendwie überlesen haben 😞

    Kannst du mir mal erklären was das genau bedeutet bzw. was da genau passiert? Vorallem wie daraus dann sowas wie "unsigned int" oder "unsigned long" wird.



  • FlashBurn schrieb:

    volkard schrieb:

    Hab ich doch mit ...

    Das muss ich irgendwie überlesen haben 😞

    Kannst du mir mal erklären was das genau bedeutet bzw. was da genau passiert? Vorallem wie daraus dann sowas wie "unsigned int" oder "unsigned long" wird.

    decltype ist neu. evtl hat Dein Compiler typeof oder __typeof__ oder so. Aber bald haben alle decltype.
    decltype liefert den Typ eines Ausdrucks.
    decltype(4) ergibt int.

    decltype(4) i;
    

    wird compiliert als

    int i;
    

    und sizeof(egal was) liefert einen size_t.
    Habe deswegen sizeof(0) genommen, weil die 0 so unauffällig ist.
    sizeof(new double(3.14)) würde mich beim Drüberlesen immer stolpern lassen.
    decltype(sizeof(0)) ergibt unsigned int oder unsigned long oder wasauchimmer auf dem Compiler gerade size_t ist.

    typedef decltype(sizeof(0)) Size;
    

    ist also automatisch das passende aus

    typedef unsigned int Size;
    
    typedef unsigned long Size;
    
    typedef unsigned long long Size;
    
    typedef unsigned __int64__ Size;
    

    usw.



  • Dann muss ich noch die Frage stellen, wie war size_t vorher (bevor man decltype hatte) definiert?



  • FlashBurn schrieb:

    Dann muss ich noch die Frage stellen, wie war size_t vorher (bevor man decltype hatte) definiert?

    Na, der Compilerbauer hat eine <size_t.h> oder so mitgeliefert, die genau auf diesen Compiler zugeschnitten war. Spätestens die <cstring> definiert size_t. Direkt oder indem sie eine nicht vom Standard geforderte <size_t.h> oder so inkludiert.
    Der Standard verlangt nur, daß der Compilerbauer Dir einen size_t zur Verfügung stellt, er muß es nicht per declytype machen, und macht es auch nicht so, sondern mit #ifdef. Den Trick habe ich außer bei mir noch nie gesehen.
    Beim Kernelbauen inkludierte man halt einen header, der size_t anbietet.



  • FlashBurn schrieb:

    Dann muss ich noch die Frage stellen, wie war size_t vorher (bevor man decltype hatte) definiert?

    Indem in einem von Compiler bereitgestellten Headerfile (stddef.h)

    typedef PassenderTyp size_t;
    

    steht.



  • Also habe das mit "decltype" gerade unter gcc 4.6.0 ausprobiert und es funktioniert nicht 😞

    Da ich unabhängig vom Compiler arbeiten möchte, nutze ich natürlich auch keine vom Compiler bereitgestellten Header-Dateien. Von daher muss ich size_t irgendwie selbst definieren.

    Habe mir auch mal versucht die Definitionen von size_t in verschiedenen Standard-Libraries (vorallem C) anzugucken und die machen das auch über einige ifdef´s 😞

    So wie ich es sehe, müsste size_t genau im Standard definiert sein und nicht vom Compiler festgelegt werden.

    Ich arbeite momentan in einer komplett unabhängigen Umgebung, sprich man braucht (theoretisch) nur nen Standard-konformen C/C++ Compiler und den Rest bringt meine Umgebung mit (auch die Header-Dateien und eventuell benötigte Library-Funktionen).



  • volkard schrieb:

    int ist immer 4 Byte.
    long 4 oder 8.

    Das ist so einfach nur falsch!

    Warum in drei Teufelnamen müssen immer wieder unfähige Programmierer so einem Mist verzapfen und ungültige Annahmen machen, die von niemanden garantiert werden! Es geht hier um C++ und das ist nicht nur auf Windows oder POSIX Systeme beschränkt! Aus diesem Grund ist es einen nur verdammt besch****, wenn hier jemand fortlaufend Falschinformationen verbreitet, und somit andere dazu verleitet diesen Mist nachzumachen. Software wird dadurch in der Portabilität eingeschränkt und läuft unter Umständen somit nicht mehr korrekt auf normierten Umgebungen, weil hier solche falschen Annahmen gemacht wurden. Muß das sein? Wohl eher nicht.



  • FlashBurn schrieb:

    Ich habe also new bei einer Klasse überschrieben. Soweit so gut. Nun meckert mich gcc voll das new einen Parameter vom Typ size_t (long unsigned int) erwartet und ich habe new mit nem Parameter vom Typ "unsigned int" deklariert.

    Für solche Fälle nimmt man ausschließlich size_t, dafür ist das da. Wenn Du etwas anderes verwendest ist das ein Bug.



  • FlashBurn schrieb:

    Also im Endeffekt zeigt das mal wieder das weder C noch C++ wirklich plattformunabhängig sind und das es ohne den Compiler zu beachten nicht möglich ist bestimmten Code (z.B. die C++ Standard-Library) zu schreiben.

    Doch das ist möglich, man muß dazu nur die vom Compiler definierten typedefs nutzen. Ich verstehe es nicht, weshalb immer wieder versucht wird statt size_t irgend etwas anderes zu verwenden.



  • FlashBurn schrieb:

    Also habe das mit "decltype" gerade unter gcc 4.6.0 ausprobiert und es funktioniert nicht 😞

    Da mußt Du zur Zeit noch C++0x per Hand anmachen.
    Und typeof hat er glaub ich schon viel länger.

    FlashBurn schrieb:

    Da ich unabhängig vom Compiler arbeiten möchte, nutze ich natürlich auch keine vom Compiler bereitgestellten Header-Dateien. Von daher muss ich size_t irgendwie selbst definieren.

    Es ist keine Schande, wenn nachher sowas rauskommt.

    #if defined __GCC__
       typedef typeof(sizeof(0)) Size;
    #elif defined __MSCVER__
       typedef _typeof(sizeof(0)) Size;
    #elif defined __THE_OTHER_CPLR__
       typedef unsigned short Size;
    #elif defined __THE_MORE_OTHER_CPLR__
       #if __MACHINE_BITS__ == 64
         typedef unsigned long Size;
       #else
         typedef unsigned int Size;
       #endif
    #else
       #error Ups, finde mal raus, wie man's mit Deinem Compiler macht und schreib's hier rein
    #endif
    

    Und das steht ja nicht ewig da. Mit C++0x ist ja versprochen, daß es decltype gibt.


Anmelden zum Antworten