Kontainergrößen



  • Hey ihr,

    Arrays, Vektoren und andere sequenzielle Kontainer haben immer eine Dimension, also die Anzahl ihrer Elemente.
    Im Netz und auch in meinem Buch steht über Beispielsweise das folgende Array:

    int cola[3]
    

    , dass es ein Array ist, was über 3 Elemente verfügt.

    int cola[3];
    
       cola[0] = 2;
       cola[1] = 4;
       cola[2] = 6;
       cola[3] = 8;
    

    Wenn ich jedoch bei 0 anfang verfügt es ja eigentlch über 4 Elemente.
    Der Quelltext oben funktioniert auch und es gibt keinen Bufferoverflow.

    Bei Vektoren ist es eigentlich das selbe:

    vector<int> flasche(3);
       flasche[0] = 2;
       flasche[1] = 4;
       flasche[2] = 6;
       flasche[3] = 8;
    

    Dieser Code funktioniert- aber nach Büchern oder Seiten im Netz müsste der Quelltext eigentlich einen Overflow verursachen.

    Kann mich hier jemand über diesen 'Fehler' in der Programmierliteratur aufklären oder mir sagen, wo der Denkfehler liegt?

    cya
    David



  • cola[3] ist bei einem C-Array erst einmal nichts anderes als die Speicheradresse hinter dem Array. Ob du eine Speicherzugriffsverletzung erzeugst ist davon abhängig was du mit dieser Adresse anfängst. Veränderst du den Speicher, wird dir das Betriebssystem zur Laufzeit eine Speicherzugrifsverletzung um die Ohren werfen.
    Bei den STL-Containern ist das ein bißchen anders. Diese können dynamisch wachsen... also wird das Element an der Stelle wohl angelegt.



  • MathiasTemp schrieb:

    cola[3] ist bei einem C-Array erst einmal nichts anderes als die Speicheradresse hinter dem Array. Ob du eine Speicherzugriffsverletzung erzeugst ist davon abhängig was du mit dieser Adresse anfängst. Veränderst du den Speicher, wird dir das Betriebssystem zur Laufzeit eine Speicherzugrifsverletzung um die Ohren werfen.

    Nein - was da passiert, ist schlicht undefiniert - und meistens steht an dieser Stelle die nächste Variable, die du in der Funktion angelegt hast.

    Bei den STL-Containern ist das ein bißchen anders. Diese können dynamisch wachsen... also wird das Element an der Stelle wohl angelegt.

    ZUmindest beim vector wird da nichts angelegt - der schreibt einfach ungeprüft hinter seine Daten (mit Glück liegt das noch innerhalb seiner Kapazität, dann passiert nichts - außer daß die Daten bei der nächsten Gelegenheit ins Nirvana verschwinden könnten, mit etwas Pech zerlegst du mit der Zuweisung interne Steuerdaten des Heap-Managers).

    @777: Beim Anlegen eines Arrays oder Containers gibst du die Größe an - da C++ bei Null mit den Indizes beginnt, ist der höchste zulässige Index 'Größe-1' (und in beiden Beispielen ist der Zugriff auf das Element 'feld[3]' undefiniert).



  • 777 schrieb:

    Der Quelltext oben funktioniert auch und es gibt keinen Bufferoverflow.

    Doch, gibts es 😉 Ein Bufferoverflow "passiert" ja nicht einfach, er wird verursacht, und zwar unabhängig davon, ob es eine Fehlermeldung gibt oder nicht. In deinem Fall hast du einen Buffer-Overflow, der keine Fehlermeldung verursacht..
    Hast du auch schön mit Debug kompiliert?



  • Achso... *uff* hatte echt schon gedacht, dass ich jetzt von Arrays doch was falsches gedacht hätte...

    Naja- mich wundert das ganze nur, weil cola[3] = 8 keinen Fehler verursacht, aber cola[4] = 10 ganz gewaltig meckert.

    Also muss ja cola 3 doch noch irgendwie... definiert sein.
    Das beim Vector einfach was hinzugefügt wird glaube ich nicht.
    Weil wozu dann push_back, push_front, insert?

    #include <iostream>
    using namespace std;
    int main(void)
    {
       int cola[1];
       cola[3] = 4;
       cout << cola[3] << endl;
       cola[4] = 5;
       cout << cola[4] << endl;
       system("Pause");
    }
    

    Letzriger Quelltext funktioniert sogar... aber vermutlich liegts dann einfach daran, was Cstoll gesagt hat, dass es eben nur durch 'Glück' funktioniert 😉

    cya
    David



  • 777 schrieb:

    Naja- mich wundert das ganze nur, weil cola[3] = 8 keinen Fehler verursacht, aber cola[4] = 10 ganz gewaltig meckert.

    Ob es "gewaltig meckert", liegt vor allem daran, welche Daten du bei deinem Überlauf schrottest - das können andere Variablen der Funktion sein (inklusive der Parameter), ungenutzte Stack-Abschnitte, aber auch die Rücksprungadresse. Im ersteren Fall bekommst du im weiteren Verlauf vermutlich unsinnige Daten, im letzten Fall kann alles passieren.



  • Trotzdem gut zu wissen, dass C++ nicht selbst auf solche Fehler achtet, sondern den Programmierer einfach ins Ungewisse rennen lässt 😉
    Naja- dann weiß ich ja jetzt bescheid *thx* 😉 😃



  • Auch ein Programmierer sollte wissen was er tut.



  • schaue dir doch einfach mal die Warnings an:

    botest.cpp(6) : warning C6201: Index '3' is out of valid index range '0' to '0' for possibly stack allocated buffer 'cola'
    botest.cpp(7) : warning C6201: Index '3' is out of valid index range '0' to '0' for possibly stack allocated buffer 'cola'
    botest.cpp(8) : warning C6201: Index '4' is out of valid index range '0' to '0' for possibly stack allocated buffer 'cola'
    botest.cpp(9) : warning C6201: Index '4' is out of valid index range '0' to '0' for possibly stack allocated buffer 'cola'
    botest.cpp(6) : warning C6386: Buffer overrun: accessing 'cola', the writable size is '4' bytes, but '16' bytes might be written: Lines: 5, 6
    botest.cpp(7) : warning C6385: Invalid data: accessing 'cola', the readable size is '4' bytes, but '16' bytes might be read: Lines: 5, 6, 7

    Sowas fängt eigentlich jeder code static analyzer ab.


Anmelden zum Antworten