[Gelöst] Speicherbereich unklar?



  • Hallo Zusammen,

    ich habe mir zum testen ein kleines Programm geschrieben, mit dem ich Ein- und Ausgabe simuliere.

    Was mich nun verwundert ist, dass ich mir ein char Array mit 10 Zeichen reserviert habe und trotzdem in der Lage bin, mehr in dieses Array zu schreiben als angegeben.

    Kann mir jemand erklären warum das möglich ist, ohne dass das Programm abstürzt?

    #include <stdio.h>
    #include <string.h>
    
    int main(int argc, char** args)
    {
    	char str[10];
    	printf("Name eingeben:\n");
    	scanf("%s", str);
    	printf("Pointer Size: %d\n - Strlen: %d\n", sizeof(str), strlen(str));
    	printf("Eingabe war: %s\n", str);
    	return 0;
    }
    
    Simulation:
    Name eingeben:
    KurtOhneHelmIstHierAngekommen
    Pointer Size: 10
     - Strlen: 29
    Eingabe war: KurtOhneHelmIstHierAngekommen
    

    Vielen Dank für eure Hilfe 😉



  • Du schreibst nicht nur in dein Array, sondern auch darüber hinaus ⚠
    Hast du Pech sieht es oberflächlich betrachtet aus als wäre das eine Lösung.
    Aber je mehr Quellcode oder andere Programme zwischen Schreiben in nicht reservierte Bereiche und Lesen liegt, desto grösser ist die Wahrscheinlichkeit das du dir Ärger einhandelst, da andere Funktionen in diesen Bereich schreiben.

    Mit Glück weisst du beim Ärger noch wann du wo gesündigt hast 😕 😡
    Wer keinen Stress hat macht sich halt mit solchen Aktionen welchen.

    Pointer Size: 10 => das glaub ich nicht so, eher String Size?



  • Breaker schrieb:

    Was mich nun verwundert ist, dass ich mir ein char Array mit 10 Zeichen reserviert habe und trotzdem in der Lage bin, mehr in dieses Array zu schreiben als angegeben.

    weil scanf nicht weiß, dass es nur 10 Bytes reserviert sind, scanf muss davon ausgehen, dass der Programmier die richtige Anzahl an Bytes im Voraus reserviert. Dein Program könnte auch mit segfault enden, weil du an über die Grenze hinaus schreibst.

    Pointer Size: 10 => das glaub ich nicht so, eher String Size?

    weder noch. In C ist die Pointersize (== Anzahl von Bytes, die benötigt werden, um einen Pointer zu speichern) für alle Typen konstant, bei x86 in der Regel 4.

    sizeof ist ein Operator, der die Anzahl von Bytes einer Variable oder Types zurückgibt, die benötigt werden, um es in Speicher darzustellen. str ist kein Pointer zondern ein Array und sizeof Array gibt die Anzahl der Bytes an, die vom Array reserviert wurden. Die ist nicht mit der String Länge gleichzusetzen, da die Stringlänge die Anzahl der Zeichen der Zeichenkette ist, die kein \0 enthält.



  • In C werden keine Arraygrenzen geprüft. Das musst du (als Programmierer machen)

    Du kannst aber scanf die maximale Eingabelänge mitgeben.

    scanf("%9s", str);  // 9, da das '\0' auch noch Platz braucht
    

    Definiere mal Variablen vor und nach deinem Array und gib dies dann noch mit aus.

    char vor[10] = "";
        char str[10];
        char nach[10] = "";
    ...
     printf("Eingabe war: <%s|%s|%s>\n", vor, str, nach);
    

    str ist als Array definiert, darum gibt dir sizeof(str) auch die Größe vom Array.
    (Bachte aber dabei, dass Arrays als Paramter von Funktionen, Pointer sind)

    char vor[10] = "";
        char str[10];
        char nach[10] = "";
    


  • ⚠ Die eigentliche Frage war ja: "Warum stürzt das Programm nicht ab".

    • Das liegt am Stack.
    • Für dein Programm ist von Start an ein gewisser speicherbereich reserviert.
    • Diese hat eine Größe X.
    • Jede Funktion die du aufrufst, legt ihre lokalen Variablen auf dem Stack ab.
    • Auch die "main".
    • Dein Array wird in der "Main" auf dem Stack abgelegt.
    • Zwar sind für dein Array nur 10 Bytes reserviert, aber hinter dem Array ist immer noch reservierter Speicher für dein Programm.
    • Dieser würde allerdings von einem zweiten Array oder von einem weiterem Funktionsaufruf verwendet, und somit nachträglich den Speicher überschreiben.
    #include <stdio.h>
    #include <string.h>
    
    int main(int argc, char** args)
    {
        char str[10];
        char arr[10];
        sprintf(str,"KurtOhneHelmIstHierAngekommen");
        printf("str: %s\n", str);
        printf("arr: %s\n", arr);
        sprintf(arr,"MeinSpeicher!");
        printf("str: %s\n", str);
        printf("arr: %s\n", arr);
        return 0;
    }
    

    Sehr schöne Frage 😃



  • Möglicherweise stürzt folgendes Programm bei zu langer Eingabe ab.

    void eingabe (char *str) 
    {
        printf("Name eingeben:\n"); 
    //    scanf("%s", str);
        gets(str); // das ist boese, nicht nachmachen.
    }
    
    int main(int argc, char** args)
    {
        char str[10];
        eingabe(str);
        printf("Pointer Size: %d\n - Strlen: %d\n", sizeof(str), strlen(str));
        printf("Eingabe war: %s\n", str);
        return 0;
    }
    

    Die Rücksprungadresse bei einem Funktionsaufruf wird auch auf dem Stack abgelegt.
    Da sie aber nach str dort liegt, kann sie überschrieben werden.

    Die Symptome sind Systemabhängig und du darfst nicht das Verhalten von deinem System/Compiler als Standard ansehen.



  • Vielen Dank für eure Erklärungen. 👍
    Ich denke es ist mir jetzt klar geworden.

    Gruß, Breaker


Anmelden zum Antworten