Problem mit Zeiger



  • Warum schließt sich das Programm sofort wieder wenn man schreibt:

    *addr = 3;

    Das ASCII Zeichen 3 wird zwar ausgebene aber danach schließt sich die Konsole sofort wieder.

    Es sein dem man schreib 2mal system("PAUSE"); unten am Ende dann schließt sich die Konsole nicht.

    Woran liegt das ?

    #include <iostream>
    using namespace std;
    
    int main()
    {
    
    char *buf = "A";
    char *var= 0 ;
    
    int  *addr =0;
    
    var = buf;
    
    addr = (int*) var ;
    *addr = 3 ;
    
    cout<<*buf;
    
     system("PAUSE");
    
    }
    


  • system("pause") ist vermeidbar und sollte vermieden werden.
    Ruf deine Konsolenanwendung über die Konsole auf (wie es sich gehört), dann schliesst sich auch dein Fenster nicht. Wenn man nur doppelklickt, dann is klar dass sich das Fenster wieder schliesst.
    Oder starte es im Debugger und setze am Ende einen Breakpoint. Ansonsten gibts zu system("pause") massig Threads hier im Forum.
    rya.



  • Beispielsweise gibt's hier (bis unten lesen!) eine Alternative:

    http://www.c-plusplus.net/forum/viewtopic-var-t-is-257376.html


  • Mod

    Deine Zeigeroperationen sind übrigens gänzlich falsch. Möglich, dass dein Programm deswegen einfach abstürzt, ohne bis zum system zu kommen.



  • frage_*_ schrieb:

    int main()
    {
    char *buf = "A";
    char *var= 0 ;
    int  *addr =0;
    var = buf;
    addr = (int*) var ;
    *addr = 3 ;
    cout<<*buf;
    

    Das Stringliteral in Zeile 3 veranlässt den Compiler ein Array mit statischer Lebenszeit anzulegen (char[2] mit 'A', '\0'). Diese Zeile initialisiert den Zeiger mit der Adresse des ersten Zeichens des Arrays. buf zeigt damit auf das Zeichen A. Beachte, diese Zuweisung ist nur aufgrund der Abwärtskompatibilität mit C zulässig. Stringliterale dürfen in beiden Sprachen nicht geändert werden. In C++ sollte man daher auch Zeiger auf const char für sie benutzen, also:

    char const *buf = "A";
    

    In Zeile 7 weist Du dem Zeiger addr über einen "versteckten" Reinterpret-Cast die Adresse des ersten Zeichens des Stringliterals zu. Dieser Cast ist schon allein deswegen problematisch, weil die Adresse in var keine gültige Adresse für addr sein muss (siehe Speicherausrichtung). In Zeile 8 dereferenzierst Du den Zeiger addr um den int-Wert 3 an der Stelle abzulegen, wohin der Zeiger zeigt. Damit versuchst Du das Stringliteral zu ändern, was nicht erlaubt ist. Es ruft undefiniertes Verhalten (UB) hervor und ein Programmabsturz ist eines von vielen möglichen Verhalten von UB (da ja nicht definiert ist, wie sich der Compiler bzw das Programm verhalten soll).



  • So funktioniert es:

    mit

    cin.sync();
    cin.get();

    geht es auch.

    #include <iostream>
    using namespace std;
    
    int main()
    {
    
    char *p="PAUSE";
    
    char *buf = "A";
    char *var= 0 ;
    
    int  *addr =0;
    
    var = buf;
    
    addr = (int*) var ;
    *addr = 3 ;
    
    cout<<*buf;
    
    system ( p ) ;
    }
    
    Wenn ich einfach schreibe system("PAUSE"); dann wird das Wort Pause wohl irgendwie überschrieben. ( hab ich nur flüchtig mit dem Debugger überprüft ).
    
    Hat jemand für mein Vorhaben vielleicht eine bessere Lösung ?
    


  • frage_*_ schrieb:

    Woran liegt das ?

    evtl. liegt das "PAUSE" im compilierten programm iwo bei deinem "A" mit deiner zeiger convertierung auf (int*) greifst du auch auf die nächsten 3 buchstaben zu die dann evtl. die buchstaben "PAU" enthalten. somit rufst dann am ende statt
    system("PAUSE"); system("XXXSE"); wobei die drei X für was beliebiges stehen was wie wo da genau ist hängt denke ich auch von der byteorder ab 😕



  • frage_*_ schrieb:

    Wenn ich einfach schreibe system("PAUSE"); dann wird das Wort Pause wohl irgendwie überschrieben. ( hab ich nur flüchtig mit dem Debugger überprüft ).

    ja das liegt daran dass gleiche strings vom compiler zusammengefasst werden (sie sollten ja idr auch schreibgeschützt sein). wenn du allerdings mit zeigern dir zugriff verschaffst kann das probleme geben.



  • frage_*_ schrieb:

    Wenn ich einfach schreibe system("PAUSE"); dann wird das Wort Pause wohl irgendwie überschrieben. ( hab ich nur flüchtig mit dem Debugger überprüft ).

    ja das liegt daran dass gleiche strings vom compiler zusammengefasst werden (sie sollten ja idr auch schreibgeschützt sein). wenn du allerdings mit zeigern dir zugriff verschaffst kann das probleme geben.



  • frage_*_ schrieb:

    So funktioniert es:

    Mag sein, dass es zu funktionieren scheint. Du hast aber immer noch undefiniertes Verhalten!

    frage_*_ schrieb:

    Wenn ich einfach schreibe system("PAUSE"); dann wird das Wort Pause wohl irgendwie überschrieben. ( hab ich nur flüchtig mit dem Debugger überprüft ).

    Das kann man erklären. Der Compiler hat im ersten Fall möglicherweise die Zeichenketten so im Speicher abgelegt

    buf,var
     addr     p
      |       |
      V       V
    +---+---+---+---+---+---+---+---+
    | A |\0 | P | A | U | S | E |\0 |      (vorher)
    +---+---+---+---+---+---+---+---+
    
    +---+---+---+---+---+---+---+---+
    | x | x | x | x | U | S | E |\0 |      (nachher)
    +---+---+---+---+---+---+---+---+
    
    (wobei 'x' die Repräsentierung der int-Zahl 3 im Speicher ist)
    

    Nach Deiner Änderung sah es vielleicht so aus:

    buf,var
      p                     addr
      |                       |
      V                       V
    +---+---+---+---+---+---+---+---+---+---+
    | P | A | U | S | E |\0 | A |\0 | ? | ? |   (vorher)
    +---+---+---+---+---+---+---+---+---+---+
    
    +---+---+---+---+---+---+---+---+---+---+
    | P | A | U | S | E |\0 | x | x | x | x |   (vorher)
    +---+---+---+---+---+---+---+---+---+---+
    

    Du hast wieder ein Stringliteral verbotenerweise verändert, und wieder über das Ende hinaus hinausgescrieben. Das erste ist aber schon schlimm genug.

    Nochmal zum mitschreiben:
    - Stringliterale dürfen nicht verändert werden!
    - char*-Zeiger darf man nicht so einfach zu int* konvertieren. Das könnte ein Alignment-Problem geben.

    Schalte bitte die Compiler-Warnungen ein und lass erstmal die Finger von C-Style Casts. Du sagst dem Compiler damit, dass Du wüsstest, was Du tust. Das scheint aber nicht der Fall zu sein.

    kk



  • 😮 hab ich doch glatt die "\0" vergessen 😞


Anmelden zum Antworten