Programm stürzt bei schreiben in argv[1] ab



  • Folgendes Programm:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define MAX 30
    
    int main(int argc, char **argv)
    {
        if(argc != 2)
        {
            printf("Syntaxfehler!\n");
            printf("Syntax: %s Dateiname\n",argv[0]);
            printf("Bitte Dateiname eingeben: ");
            fgets(argv[1],MAX,stdin);
            unsigned char length = strlen(argv[1]);
            argv[length-1] = '\0';
        }
    }
    

    lässt mich zuerst einen String eingeben, und sobald ich Enter drücke stürzt es ab.(Process returned -1073741819 (0xC0000005))

    Eigentlich sollte es in argv[1] schreiben, damit es auch einen Dateinamen kennt, wenn beim aufrufen des Programms keiner über die Kommandozeile übergeben wurde.



  • Also wie jetzt? Ist argc kleiner 2? Dann ist argv[1] ein sinnloser Ausdruck, aus dem man keinen Zeiger konstruieren sollte. Oder ist argc grösser 2? Dann ist argv[1] ein Zeiger auf einen Bereich, von dem keiner sagen kann, wie gross er wirklich ist, ausser dass er mindestens so gross sein wird, wie das zweite Argument.

    Ob man überhaupt in die Bereiche schreiben sollte, die verwendet werden, um die argv-Strings zu halten?

    C99 5.1.2.2.1 schrieb:

    The parameters argc and argv and the strings pointed to by the argv array shall
    be modifiable by the program, and retain their last-stored values between program
    startup and program termination.

    Sieht so aus, als dürfte man das. Aber dort sollte auch genügend Platz sein.



  • Habe folgende Zeile:

    argv[1] = (char *) malloc(30);
    

    hinzugefügt.

    Das Programm läuft jetzt.



  • Damit überschreibst du argv, das hat dann nichts mehr mit dem argv zu tun was du übergeben bekommst. Das sollte man der Lesbarkeit wegen lassen.



  • Damit überschreibst du argv, das hat dann nichts mehr mit dem argv zu tun was du übergeben bekommst. Das sollte man der Lesbarkeit wegen lassen.

    Macht ja nichts! Der Standard hat sichtlich nichts dagegen. Und es ist sicher schlauer, die Zeiger umzubiegen, als den ursprünglichen Bereich zu verwenden.



  • Anonym_ schrieb:

    Habe folgende Zeile:

    argv[1] = (char *) malloc(30);
    

    hinzugefügt.

    Das Programm läuft jetzt.

    Jo, fragt sich nur, wie lange. Kein malloc ohne free ist die Regel.
    Wenn der Kontext nach Beedigung der Main genullt wird, kein Problem. Außerhalb der Main existiert das Objekt aber offiziell nicht mehr.
    Also entweder schafft er sich ein MemoryLeak oder den Umstand, daß er sich hasardeurisch darauf verläßt, daß das Objekt außerhalb der Main noch konsistent auslesbar ist.
    Ist alles unbefriedigend, aber eigentlich sollte man schlimmstenfalls nur den reingereichten Datenbereich nutzen und rereferencing strengstens vermeiden.



  • µngbd schrieb:

    Damit überschreibst du argv, das hat dann nichts mehr mit dem argv zu tun was du übergeben bekommst. Das sollte man der Lesbarkeit wegen lassen.

    Macht ja nichts! Der Standard hat sichtlich nichts dagegen. Und es ist sicher schlauer, die Zeiger umzubiegen, als den ursprünglichen Bereich zu verwenden.

    Ja, es funktioniert. Ich behaupte nur, es tut es nicht so wie es gedacht war. Oder ich verstehe den Sinn nicht. Oder es gibt einfach keinen 😉



  • nwp2 schrieb:

    Ja, es funktioniert. Ich behaupte nur, es tut es nicht so wie es gedacht war. Oder ich verstehe den Sinn nicht. Oder es gibt einfach keinen 😉

    🙂
    Ich auch nicht. Aber das hab ich mir abgewöhnt.

    Übrigens hab ich auch schon einmal ernsthaft einen Zeiger in argv verändert, aber das war nur ein Hack, weil ich zu faul war, meinen Argument-Parser zu umzubauen.


Anmelden zum Antworten