Zugriffsprobleme



  • Hallo,

    ich habe mir in einer Klasse eine statische Methode zum Trimmen von einem char-Array geschrieben.
    Und weil ich mich hier melde... funktioniert es natürlich nicht 😕

    Wenn der Code abschmiert, kann ich in meinem Debugger noch die Werte zum Zeitpunkt des Absturzes ansehen und die machen alle Sinn. Anbei der Code:

    Main.cpp

    int main(){
       char* s = "   Hallo Welt!   "; //17 Zeichen inkl. der Leerzeichen
       cout << "Vorher: " << s << endl;
       MyFunction::Trim(s, 17);
       cout << "Nachher: " << s << endl;
       return 0;
    }
    

    MyFunction.h

    class MyFunction{
       public:
       static void Trim(char* s, unsigned int Length){
    	unsigned int fi = 0, fj = 0, fStart = 0, fEnd = Length - 1;
    	char* sc = new char[Length];
    	strcpy(sc, s);
    
    	while (s[fStart] == ' '){ fStart++; }
    	while (s[fEnd] == ' '){ fEnd--; }
    
    	for (fi = fStart; fi <= fEnd; fi++){
    		s[fj++] = sc[fi]; //Hier steigt der Debugger aus
                    /*Eine Überprüfung von s und sc ergibt, dass beide
                    "   Hallo Welt!   " enthalten. 
                    Variablen:
                    fi = fStart = 3, fEnd = 13, fj=0*/
    	}
    
    	s[fj] = '\0';
    	free(sc);
       }
    }
    

    Der Fehler lautet:
    "Ausnahmefehler bei 0x000000013FB498C9 in ReadNastranMesh3D.exe: 0xC0000005: Zugriffsverletzung beim Schreiben an Position 0x000000013FB54188"

    Sorry, aber ich verstehe es nicht. In s[0] scheint er nicht zu schreiben dürfen.
    Kann es an dem "static" void liegen?

    Vielen Dank, dass Ihr Euch das anseht.

    Grüße,
    CJens



  • Darf er auch nicht, dein " Hallo Welt! " liegt in schreibgeschütztem Speicher.

    Du könntest dir dein Leben um nen großen Faktor leichter machen, wenn du std::string benutzen würdest, vorallem da du hier im C++ Forum fragst. Du hast da aber C Code.



  • KN4CK3R schrieb:

    Du hast da aber C Code.

    Bitte, in C++ kann vieles als C Code bezeichnet werden. Trotzdem ist es gueltiges C++.

    Ansonsten:

    char* sc = new char[Length];
    

    Sollte mit delete freigegeben werden. malloc und new muessen sich nicht gut vertragen.



  • ...und kann ich den Speicher irgendwie für ihn freigeben?

    Die Zeichenkette ist deshalb ein Char, weil ich die Daten aus einer formatierten Datei auslese, ich bis vor kurzem reines C Programmiert habe, jetzt aber versuche auf C++ zu erweitern und, weil ich auch keine Methode zum Trimmen von Strings gefunden habe... was nicht heissen muss, dass es keine gibt. Hab was aus dem Header <ctype.h> gefunden... aber ich will keinen kompletten Header einbinden, weil ich einmal eine Funktion brauche... vor allem, wenn meine Funktion ja methodisch funktioniert.

    Ich würde daher trotzdem gerne wissen, wie eine Methode aus meiner Klasse eine Variable von der Main-Funktion, dessen Adresse die Methode kennt, verändern kann. Geht das?



  • knivil schrieb:

    KN4CK3R schrieb:

    Du hast da aber C Code.

    Bitte, in C++ kann vieles als C Code bezeichnet werden. Trotzdem ist es gueltiges C++.

    Ansonsten:

    char* sc = new char[Length];
    

    Sollte mit delete freigegeben werden. malloc und new muessen sich nicht gut vertragen.

    Hi, also das habe ich geändert... ändert aber nichts an dem Fehler. Anbei der aktuelle Code:

    static void Trim(char* s, unsigned int Length){
    	unsigned int fi = 0, fj = 0, fStart = 0, fEnd = Length - 1;
    	char* sc = new char[Length];
    
    	strcpy(sc, s);
    
    	while (s[fStart] == ' '){ fStart++; }
    	while (s[fEnd] == ' '){ fEnd--; }
    
    	for (fi = fStart; fi <= fEnd; fi++){
    		s[fj++] = sc[fi];
    	}
    
    	s[fj] = '\0';
    	delete(sc);
    	}
    


  • Geht das?

    Ja geht.

    Variable von der Main-Funktion

    Der Zeiger liegt in main , aber dein String " Hallo Welt! " liegt woanders. Loesung: char s[145] = " jeha machen ". Btw. leider trimmt dein Funktion den String nicht, sondern verschiebt ihn nur im Speicher.



  • knivil schrieb:

    KN4CK3R schrieb:

    Du hast da aber C Code.

    Bitte, in C++ kann vieles als C Code bezeichnet werden. Trotzdem ist es gueltiges C++.

    klar, ist es gültiges C++ und trotzdem ist sein Code in der Form im C Forum besser aufgehoben. Sein Name ist ja auch CJens und nicht C++Jens.

    Dein Code geht immernoch nicht, weil du immernoch auf schreibgeschützten Speicher zugreifst. Entweder kopierst du s und gibst die Kopie zurück + kümmerst dich um die Speicherverwaltung oder halt std::string.



  • Das Problem ist, das s auf eine Speicherbereich zeigt, den du nicht verändern darfst.

    Entweder machst du in main

    char s[] = "   Hallo Welt!   ";
    

    Dann hast du ein Array (auf dem Stack).

    Oder du machst das char* sc = new char[Length]; in main. Dann kannst du das Stringliteral dahin kopieren. (Dann musst du aber auch sc an Trim übergeben)

    Den Speicher in Trim zu besorgen bringt mit void als Rückgabewert nicht viel.



  • DirkB schrieb:

    Das Problem ist, das s auf eine Speicherbereich zeigt, den du nicht verändern darfst.

    Entweder machst du in main

    char s[] = "   Hallo Welt!   ";
    

    Dann hast du ein Array (auf dem Stack).

    Oder du machst das char* sc = new char[Length]; in main. Dann kannst du das Stringliteral dahin kopieren. (Dann musst du aber auch sc an Trim übergeben)

    Den Speicher in Trim zu besorgen bringt mit void als Rückgabewert nicht viel.

    Vielen Dank, funktioniert wunderbar... 👍 😋

    main.cpp

    char* s = new char[18];
    	strcpy(s, "   Hallo Welt!   \0");
    	cout << "Vorher: " << s << endl; //   Hallo Welt!   #ENDE
    	MyFunction::Trim(s, 18);
    	cout << "Nachher: " << s << endl;//Hallo Welt!#ENDE
    

    MyFunction.h

    unsigned int fi = 0, fj = 0, fStart = 0, fEnd = Length - 1;
    	char* sc = new char[Length];
    
    	strcpy(sc, s);
    
    	while (s[fStart] == ' '){ fStart++; }
    	while (s[fEnd] == ' '){ fEnd--; }
    
    	for (fi = fStart; fi <= fEnd; fi++){
    		s[fj++] = sc[fi];
    	}
    
    	s[fj] = '\0';
    	delete(sc);
    


  • Das Gegenstück von new[] ist delete[], delete ist das Gegenstück von new.

    delete[] sc;
    


  • In einem Stringliteral brauchst du die \0 nicht mit angeben. Das macht der Compiler automatisch.
    Und daher kann Trim die Länge auch alleine feststellen. Daher ist der Parameter Length überflüssig.

    sc brauchst du auch nicht in Trim.
    Zeile 10 wäre dann s[fj++] = s[fi];



  • Uups, habe falsch gelesen, zweimal fj



  • s[fj++] = s[fi];
    

    ist vergleichbar mit

    s[fj] = s[fi]
    fj++;
    

    Btw: Als C++ Programmierer iteriere ich auch manchmal gern so:

    v = *jeha++
    

    Ansonsten: Nur die Harten kommen in den Garten. 🙂



  • volkard schrieb:

    DirkB schrieb:

    Zeile 10 wäre dann s[fj++] = s[fi];

    Da hätte ich ein wenig Bammel, wann genau das ++ bewirkt wird.

    fj und fi sind unterschiedliche Variablen.



  • knivil schrieb:

    KN4CK3R schrieb:

    Du hast da aber C Code.

    Bitte, in C++ kann vieles als C Code bezeichnet werden. Trotzdem ist es gueltiges C++.

    Ansonsten:

    char* sc = new char[Length];
    

    Sollte mit delete freigegeben werden. malloc und new muessen sich nicht gut vertragen.

    Hi,

    also, das klappt soweit ganz gut, dass man den einzelnen Komponenten des Arrays sofort einen Wert zuweist. Bei den char arrays ist das egal, aber kann man, wenn man z.B. ein int Array benötigt und über

    int* Arr = new int[nArr]; //Alte Speicherwerte bleiben
    

    auch festlegen, dass alle Felder den Wert 0 haben? Das ist nämlich nicht so. Wenn ich jedoch

    int* Arr = (int*)calloc(nArr, sizeof(int)); //Alle Komponenten mit 0 initialisiert
    

    benutze, ist das komplette Array mit 0 initialisiert. Kann man das über "new" auch machen?



  • int* Arr = new int[nArr](0);
    

Log in to reply