Verwirrender Speicherzugriffsfehler beim erhöhen von Integern



  • Okay. Nutze C++ unter OpenSuse mit Geany, derzeit für ein kleineres Spiel mit SDL.
    Innerhalb des Spieles lese ich ,txt Dateien aus.
    Nun habe ich zwei Integer, die beide gleich initiiert werden:

    int EnemyNumber = 1;
    int Umgebung = 1;

    Anschließend lese ich die Textdatei zeile für Zeile aus, kürze die Ausgabe nach dem = Zeichen, und setze die Werte entsprechend, z.B:

    if(zeilenspeicher=="Name")
    		  {
    			Current.Name=zeilenleser;
    			cout << zeilenleser;
    		  }
    

    Wenn ich nun aber folgendes Eintrage:

    if(zeilenspeicher=="ENew")
    		  {
    			EnemyNumber++;
    			EnemyscriptBuffer=0;
    			cout << zeilenleser;
    		  }
    

    funktioniert das Wunderbar.während:

    if(zeilenspeicher=="ONew")
    		  {
    			Umgebung++;
    			cout << zeilenleser;
    		  }
    

    Einen Speicherzugriffsfehler erzeugt, und

    if(zeilenspeicher=="ONew")
    		  {
    			Umgebung=666;
    			cout << zeilenleser;
    		  }
    

    Auch wieder funktioniert-
    hat irgendjemand den Hauch einer Ahnung woran soetwas liegen kann?



  • Lies dir bitte das durch.



  • Nexus schrieb:

    Lies dir bitte das durch.

    Das bringt mir wenig, ich suche generell nach Ideen wie soetwas zustande kommt-
    die Variable wird bisher an keiner anderen Stelle verwendet, das Problem tritt auch auf wenn die If-Abfrage niemals zutrifft (in der geposteten Form)-
    unter welchen Umständen kann ein int nicht flexibel verändert werden?



  • Solche Bugs können durch undefiniertes Verhalten entstehen. Mögliche Ursachen sind Array-Überläufe, Dereferenzierung ungültiger Zeiger oder fehlerhafte Verwendung der Speicherverwaltung.

    Diese Probleme kannst du massiv eindämmen, wenn du modernes C++ verwendest und Low-Level-Operationen kapselst: RAII, std::array statt Arrays, std::unique_ptr statt new , std::vector statt new[] , std::string statt char* , ...



  • Danke, das ist auf jeden Fall gut zu Wissen-
    bei mir ist dieses Problem gerade ebenso unerklärlich verschwunden wie es zuvor Auftrat (habe gut zwei Stunden daran herumgefrickelt Oo).



  • Mache nicht den Fehler und glaube, dass das Problem behoben sei. Wenn du undefiniertes Verhalten im Programm hast, solltest du es unbedingt ausmerzen. Du hast nämlich dein Programm nicht mehr unter Kontrolle. Mehr Code zu schreiben macht es nur noch schwieriger, den Bug zu finden...

    Und berücksichtige meinen Hinweis im Bezug auf modernes C++. Ich bin mir fast sicher, dass da nicht alles eingehalten wurde.


  • Mod

    Mumbo schrieb:

    Danke, das ist auf jeden Fall gut zu Wissen-
    bei mir ist dieses Problem gerade ebenso unerklärlich verschwunden wie es zuvor Auftrat (habe gut zwei Stunden daran herumgefrickelt Oo).

    Das ist auch normal bei undefiniertem Verhalten. Das heißt aber nicht, dass der Fehler behoben wurde, sondern bloß, dass er sich derzeit nicht (sichtbar) äußert. Erfahrungsgemäß wird sich dies schlagartig wieder ändern, sobald du das vermeintlich fehlerfreie Programm deinem Chef vorführst.



  • Oder sonst wie verbreitest... 🙄



  • Erstmals nochmal Danke für die Antworten

    Nunja, hoffe das es irgendein sehr komischer Fehler war den ich jetzt erfolgreich ausgemerzt habe (wobei eure Vermutung durchaus berechtigt ist - mein Quelltext ist ein gigantischer Verstoß gegen jeden Standard der jemals irgendwo definiert wurde). Bin aber ein absoluter Dilettant & wäre mit sauberem Programierstil heillos überfordert (so frißt z.B. die SDL auch nur char* 😉 - bin also schon froh wenn es ungefähr funktioniert - und im Endeffekt habe ich dadurch den Vorteil das Vorführungen beim Chef & jeglicher Zeitdruck weitgehend Entfallen.
    Wenn der Fehler wieder auftritt wäre das dementsprechend Schade, aber vielleicht habe ich ja Glück- vorhin kam er wirklich instant bei jedem Aufruf, jetzt kam er immerhin schon ca. 15x in Folge überhaupt nicht ^^



  • Mumbor schrieb:

    (so frißt z.B. die SDL auch nur char* 😉

    std::string::c_str() hilft da...



  • ...oder modernere APIs wie SFML :p

    Mumbor, musst du natürlich selber wissen. Mir ist auch klar, dass Refactoren existierender Projekte nicht immer eine Option ist. Ich würde mir aber wenigstens für neue Projekte vornehmen, gewisse Richtlinien zu beachten. Die Meinung, dass du dadurch mehr Zeit brauchst, ist Irrglaube. Das Gegenteil ist der Fall: Du musst dir nicht dauernd Gedanken um Speicherverwaltung machen, wenn du RAII benutzt. Du bist schneller in der Entwicklung, Code wird kürzer und besser verständlich, und ist sicherer, ohne dabei an Geschwindigkeit einzubüssen. Du hast nur Vorteile.


  • Mod

    Nexus schrieb:

    Die Meinung, dass du dadurch mehr Zeit brauchst, ist Irrglaube. Das Gegenteil ist der Fall: Du musst dir nicht dauernd Gedanken um Speicherverwaltung machen, wenn du RAII benutzt. Du bist schneller in der Entwicklung, Code wird kürzer und besser verständlich, und ist sicherer, ohne dabei an Geschwindigkeit einzubüssen. Du hast nur Vorteile.

    Nicht zu vergessen: Verwirrende Speicherzugriffsfehler beim Erhöhen von Integern sind ebenfalls so gut wie ausgestorben. Oder falls man doch mal einen hat, dann sind sie sehr viel einfacher zu finden.



  • Warum gibts eigentlich keinen pointer_wrapper?
    Der einem einen Assert um die Ohren haut, wenn man vergessen hat, dem nullptr einen Wert zu geben. 🙄


  • Mod

    Nathan schrieb:

    Warum gibts eigentlich keinen pointer_wrapper?
    Der einem einen Assert um die Ohren haut, wenn man vergessen hat, dem nullptr einen Wert zu geben. 🙄

    😕 Meinst du Referenzen?



  • Nein,ich will einfach nur sicherer variable, ggf ungültige Verweise auf ein Objekt.


  • Mod

    Einen Laufzeitfehler a la assert bekommst du doch, wenn du einen falschen Pointer benutzt. Ich verstehe deinen Featurewunsch nicht.



  • OK, nochmal besser erklärt.
    Ich brauche ab und zu, einen änderbaren und ggf. ungültigen Verweis auf ein anderes Objekt. Dafür muss ich einen (rohen) Pointer nutzen.
    Ich hatte mich ewig mit Speicherzugriffsfehlern herum schlagen müssen, weil ich den Pointer vergessen hatte zu initialisieren. Deswegen habe ich mir eine Wrapper-Klasse um einen rohen Pointer geschrieben, der ihn ordnungsgemäß initalisiert und vorm Dereferenzieren via assert() prüft, ob der Pointer einen Wert hat. Wäre schön, wenn es sowas im Standard gäbe.



  • vorm Dereferenzieren via assert() prüft, ob der Pointer einen Wert hat.

    Zeiger koennen Werte besitzen, hne dass sie dereferenzierbar sind. Auch gibt es Smart-Pointer, die deinen Wuenschen entsprechen.



  • Das einzige, was dafür in Frage kommen würde, wäre std::weak_ptr<>. Alle anderen Pointer löschen die Objekte im Destruktor. Und wenn ich lock() mache um darauf zuzugreifen, wird ein shared_ptr<> erzeugt, was auch überflüssig ist. Ich will einfach nur einen simplen Verweis auf ein Objekt auf dem Stack.


Log in to reply