size_t Overflow erkennen



  • Okay, vielen Dank, das ergibt Sinn. Den <<-Operator kannte ich auch noch nicht, damit erspart man sich die wohl doch sehr langsame power-Funktion (bzw. das Schreiben einer eigenen schnelleren für int-Typen).

    Kurze Frage noch: Ist es eigentlich möglich, einen Array anzulegen, der mehr Einträge hat, als man mit dem Typen size_t darstellen kann? Gibt es nicht irgendwann bei solchen extremen Größen Probleme mit der Adressierung?

    Edit: Kann ich mir überhaupt sicher sein, dass beim Umgang eines Arrays mit max size_t vielen Einträgen (Objekten) alles gut geht (abgesehen davon, dass der physische Speicher recht schnell voll sein wird)?

    Das sind jetzt alles etwas hypothetische Fragen - ich bin halt gerade dabei, einen exponentiellen Algorithmus (Laufzeit und Speicher) zu implementieren, um einfach zu sehen, wie schnell man da an die Grenzen stößt (wohl sehr schnell).



  • plizzz schrieb:

    Kurze Frage noch: Ist es eigentlich möglich, einen Array anzulegen, der mehr Einträge hat, als man mit dem Typen size_t darstellen kann?

    AFAIK nicht, nein.

    Gibt es nicht irgendwann bei solchen extremen Größen Probleme mit der Adressierung?

    Würde es geben. Aus dem Grund ist size_t so gut wie immer sowas wie unsigned int, hat also je nach Betriebssystem auf "normalen" PCs 32 oder 64 bit. Aus dem Grund sind jetzt auch die 64bit Systeme im Kommen, weil man mit 32 bit eben nur <4GB Speicher adressieren kann.

    Edit: Kann ich mir überhaupt sicher sein, dass beim Umgang eines Arrays mit max size_t vielen Einträgen (Objekten) alles gut geht (abgesehen davon, dass der physische Speicher recht schnell voll sein wird)?

    Abgesehen davon dass du so viel Speicher vermutlich nicht wirst anfordern können, kannst du dir sicher sein, dass du damit ganz normal arbeiten kannst, wenn du ihn erstmal hast. Natürlich mit entsprechenden Performanceproblemen...


  • Mod

    plizzz schrieb:

    Kurze Frage noch: Ist es eigentlich möglich, einen Array anzulegen, der mehr Einträge hat, als man mit dem Typen size_t darstellen kann? Gibt es nicht irgendwann bei solchen extremen Größen Probleme mit der Adressierung?

    size_t ist groß genug, um die Größe eines jeden einzelnen Objektes beschreiben zu können, ein Array ist auch so ein Objekt. Die Antwort ist also nein. Es ist allerdings möglich, dass die Gesamtmenge des verfügbaren Speichers nicht in ein size_t passt, dieser Speicher kann dann aber nicht als ein zusammenhängendes Objekt verwendet werden.

    Tim schrieb:

    camper schrieb:

    Vorausgesetzt, alle Bits von size_t nehmen an der Wert-Repräsentation teil. Das ist zwar wahrscheinlich, aber nicht garantiert.

    Kennst du auch nur ein System bei dem das nicht zutrifft?

    Ich hoffe, du beabsichtigst nicht, hier ein Argument anhand meines Wissens oder Nichtwissens anzubringen?



  • Tim schrieb:

    camper schrieb:

    Vorausgesetzt, alle Bits von size_t nehmen an der Wert-Repräsentation teil. Das ist zwar wahrscheinlich, aber nicht garantiert.

    Kennst du auch nur ein System bei dem das nicht zutrifft?

    Irgendwann landet mal ein Alien-Raumschiff auf der Erde und dann hängt die Rettung der Welt davon ab, dass dein C++ Code fehlerfrei auf diesem Raumschiff läut. Auf diesem Raumschiff hat ein Byte 11 Bits und sie verwenden das letzte nicht, aber sie haben einen C++ Compiler.



  • Nicht irgendwann. Noch dieses Jahr. 😮



  • camper schrieb:

    Tim schrieb:

    camper schrieb:

    Vorausgesetzt, alle Bits von size_t nehmen an der Wert-Repräsentation teil. Das ist zwar wahrscheinlich, aber nicht garantiert.

    Kennst du auch nur ein System bei dem das nicht zutrifft?

    Ich hoffe, du beabsichtigst nicht, hier ein Argument anhand meines Wissens oder Nichtwissens anzubringen?

    Es geht mir nicht darum ob du eines kennst, sondern ob es sowas wirklich gibt. Denn ich kenne keines. Und ganz ehrlich, ich sehe es nicht ein so einen konstruierten Fall in SW zu berücksichtigen. Und wenn mal eine Architektur sowas macht, dann soll sie meine SW gar nicht spielen dürfen 😉

    ~**^°#{[< schrieb:

    Tim schrieb:

    camper schrieb:

    Vorausgesetzt, alle Bits von size_t nehmen an der Wert-Repräsentation teil. Das ist zwar wahrscheinlich, aber nicht garantiert.

    Kennst du auch nur ein System bei dem das nicht zutrifft?

    Irgendwann landet mal ein Alien-Raumschiff auf der Erde und dann hängt die Rettung der Welt davon ab, dass dein C++ Code fehlerfrei auf diesem Raumschiff läut. Auf diesem Raumschiff hat ein Byte 11 Bits und sie verwenden das letzte nicht, aber sie haben einen C++ Compiler.

    Systeme mit CHAR_BIT != 8 sind übrigens nicht sooo unüblich.


  • Mod

    Tim schrieb:

    camper schrieb:

    Tim schrieb:

    camper schrieb:

    Vorausgesetzt, alle Bits von size_t nehmen an der Wert-Repräsentation teil. Das ist zwar wahrscheinlich, aber nicht garantiert.

    Kennst du auch nur ein System bei dem das nicht zutrifft?

    Ich hoffe, du beabsichtigst nicht, hier ein Argument anhand meines Wissens oder Nichtwissens anzubringen?

    Es geht mir nicht darum ob du eines kennst, sondern ob es sowas wirklich gibt. Denn ich kenne keines. Und ganz ehrlich, ich sehe es nicht ein so einen konstruierten Fall in SW zu berücksichtigen. Und wenn mal eine Architektur sowas macht, dann soll sie meine SW gar nicht spielen dürfen 😉

    ~**^°#{[< schrieb:

    Tim schrieb:

    camper schrieb:

    Vorausgesetzt, alle Bits von size_t nehmen an der Wert-Repräsentation teil. Das ist zwar wahrscheinlich, aber nicht garantiert.

    Kennst du auch nur ein System bei dem das nicht zutrifft?

    Irgendwann landet mal ein Alien-Raumschiff auf der Erde und dann hängt die Rettung der Welt davon ab, dass dein C++ Code fehlerfrei auf diesem Raumschiff läut. Auf diesem Raumschiff hat ein Byte 11 Bits und sie verwenden das letzte nicht, aber sie haben einen C++ Compiler.

    Systeme mit CHAR_BIT != 8 sind übrigens nicht sooo unüblich.

    Gegen CHAR_BIT ist gar nichts einzuwenden, denn bei char wissen wir, dass Objekt- und Wertrepräsentation übereinstimmen. Die Verwendung sizeof hingegen führt in die Irre, denn dieser Wert bezieht sich eindeutig auf das Objekt und nicht den Wert. Da beide Reoräsentationen (aus gutem Grund) für gewöhnlich übereinstimmen, mag die die sizeof-Variante in einem sehr weit gefassten Sinn "funktionieren". A zu sagen, wenn B gemeint ist, ist trotzdem ein (logischer) Fehler auch dann, wenn zufällig mal A==B gilt.



  • Bei mir kommt dabei die Frage auf: wie lösen die in C das Problem?
    Die haben nunmal nur sizeof.
    Ist in C definiert, dass size_t alle Bits nutzt und in C++ nicht?


  • Mod

    DrakoXP schrieb:

    Bei mir kommt dabei die Frage auf: wie lösen die in C das Problem?
    Die haben nunmal nur sizeof.
    Ist in C definiert, dass size_t alle Bits nutzt und in C++ nicht?

    Es gibt noch SIZE_MAX ... und daraus binäre Stellen zu machen, ist die Aufgabe des Programmierers.



  • DrakoXP schrieb:

    Bei mir kommt dabei die Frage auf: wie lösen die in C das Problem?

    Welches Problem? Das theoretische? Nein, in C lösen wir doch lieber reale 😉



  • pumuckl schrieb:

    plizzz schrieb:

    Kurze Frage noch: Ist es eigentlich möglich, einen Array anzulegen, der mehr Einträge hat, als man mit dem Typen size_t darstellen kann?

    AFAIK nicht, nein.

    Gibt es nicht irgendwann bei solchen extremen Größen Probleme mit der Adressierung?

    Würde es geben. Aus dem Grund ist size_t so gut wie immer sowas wie unsigned int, hat also je nach Betriebssystem auf "normalen" PCs 32 oder 64 bit. Aus dem Grund sind jetzt auch die 64bit Systeme im Kommen, weil man mit 32 bit eben nur <4GB Speicher adressieren kann.

    Edit: Kann ich mir überhaupt sicher sein, dass beim Umgang eines Arrays mit max size_t vielen Einträgen (Objekten) alles gut geht (abgesehen davon, dass der physische Speicher recht schnell voll sein wird)?

    Abgesehen davon dass du so viel Speicher vermutlich nicht wirst anfordern können, kannst du dir sicher sein, dass du damit ganz normal arbeiten kannst, wenn du ihn erstmal hast. Natürlich mit entsprechenden Performanceproblemen...

    Ah okay, das heißt dann also, dass ich insgesamt nur sizeof(size_t) viele Bytes an Speicher überhaupt adressieren kann (ist das die "Definition" von size_t ?)?



  • std::size_t kann schlicht für alle Speichergrößen verwendet werden und ist eigentlich immer exakt so groß, um jedes Byte das der Prozessor addressieren kann auch selbst darstellen könnte. Wären unter 64bit immerhin 16.777.216 Terrabyte, also genug. 😉



  • Ethon schrieb:

    std::size_t kann schlicht für alle Speichergrößen verwendet werden und ist eigentlich immer exakt so groß, um jedes Byte das der Prozessor addressieren kann auch selbst darstellen könnte. Wären unter 64bit immerhin 16.777.216 Terrabyte, also genug. 😉

    Muß nicht sein. Stell Dir DOS vor mit einem Speichermodell, wo kein Objekt größer als 64k sein kann, aber Zeiger 32-bittig sind.
    Desdawegen ist ja auch die Adressvergleicherei in C++ nicht garantiert, wenn man Zeiger aus verschiedenen Objekten vergleicht.

    Aber faktisch kann man davon ausgehen. Da reicht es sogar, wie ich eingangs sagte, gegen 0 zu prüfen (also (sizeof(Element)<<n)==0 mit einer Zweierpotenz als sizeof(Element)).


  • Mod

    volkard schrieb:

    Da reicht es sogar, wie ich eingangs sagte, gegen 0 zu prüfen (also (sizeof(Element)<<n)==0 mit einer Zweierpotenz als sizeof(Element)).

    Nicht zu empfehlen.

    C++11 schrieb:

    5.8 Shift operators [expr.shift]
    1 The shift operators << and >> group left-to-right.
    shift-expression:
    additive-expression
    shift-expression << additive-expression
    shift-expression >> additive-expression
    The operands shall be of integral or unscoped enumeration type and integral promotions are performed.
    The type of the result is that of the promoted left operand. The behavior is undefined if the right operand
    is negative, or greater than or equal to the length in bits of the promoted left operand.



  • Danke schonmal für die vielen Antworten, der Thread hat mir schon ein wenig geholfen, mein Wissen zu erweitern.

    Noch eine kurze Frage zu dem <<-Operator. Wie verhält es sich hier mit impliziten Typedefs?

    Angenommen: Ich schreibe a << b, wobei a ein Short ist und b ein unsigned long? Das hat insofern Relevanz, dass der Ausdruck bei short einen Overflow geben könnte, während er bei unsigned long keine Probleme verursacht. Was ist, wenn ich links ein Literal stehen habe? Welchen Typ hat dann der Ausdruck 1<<n? Kann ich davon ausgehen, dass er den gleichen Typ hat wie n?

    Die gleiche Frage stellt sich bei mir gerade mit Addition:
    Angenommen, ich habe eine int a und eine unsigned long b und berechne a + b. Eigentlich müsste das Ergebnis Typ int haben, da dabei eben auch negative Werte auftreten können. Wäre andererseits aber etwas paradox, denn man könnte dann ja einfach Overflows produzieren, selbst wenn a zB den Wert 0 hat (und b größer als max_int ist).

    Übrigens kann man sich das mit CHAR_BITS wohl auch sparen, wenn man die Funktion digits aus limits.h benutzt: [Return-Wert] For integer types: number of non-sign bits (radix base digits) in the representation.



  • plizzz schrieb:

    Angenommen, ich habe eine int a und eine unsigned long b und berechne a + b. Eigentlich müsste das Ergebnis Typ int haben, da dabei eben auch negative Werte auftreten können.

    Der Typ ist unsigned long.
    Die Regeln nach denen das abläuft stehen z.B. hier:
    http://msdn.microsoft.com/en-us/library/09ka8bxx(v=VS.80).aspx



  • Okay danke. DAs ist gut zu wissen und ergibt Sinn.



  • Ich grade den Thread mal wieder aus. Und zwar ist es nun so, dass size_t bei mir 32 bits groß ist, ich allerdings ein 64-Bit System habe. Steht das nicht im Widerspruch zur Idee von size_t?



  • plizzz schrieb:

    Ich grade den Thread mal wieder aus. Und zwar ist es nun so, dass size_t bei mir 32 bits groß ist, ich allerdings ein 64-Bit System habe. Steht das nicht im Widerspruch zur Idee von size_t?

    Du kompilierst im 64bit Modus?



  • Darüber habe ich mir noch gar keine Gedanken gemacht - ich kompiliere einfach, sozusagen. Aber das wird dann wohl nicht der 64bit Modus sein und damit ist die Frage dann geklärt. Heißt das dann auch, dass so Dinge wie sizeof(Datentyp), CHAR_BIT, INT_MAX, ... beim Zeitpunkt der Kompilierung und nicht während der Laufzeit festgelegt werden?


Anmelden zum Antworten