Zugriffsverletzung



  • /* Bekomme beim Compilieren immer die Fehlermedlung: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0xcdcdcdcd. Hab mich schon mal erkundigt das diese Fehlermeldung häufig bei Überschreitung von Speicherbereich kommt. Mein char datum array wird jedoch nie zu voll.

    Vielleicht findet ihr ja den Fehler (hab ein KOmmentat hinter die Zeile gesetzt)

    Vielen Dank im Voraus 😉

    */

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class ListenElement
    {
    
    private:
    	int tagesproduktion;
    	char datum[11];
    	ListenElement *next;
    
    public:
    	ListenElement(){} // default konstruktor
    	ListenElement(int tagesp, char dat[], ListenElement el) //Konstruktor
    	{
    		tagesproduktion = tagesp;
    		strncpy(datum,dat,12);
    		next = &el;
    	}
    
    	friend class Produktionsliste;
    
    };
    
    class Produktionsliste
    {
    private:
    	ListenElement *first, *last;
    
    public:
    	Produktionsliste() // Default Konstruktor
    	{
    		first = NULL;
    		last = NULL;
    	}
    
    	void insert(int val, char dat []) // Elemente in Liste einfügen
    	{
    		ListenElement *newelem = new ListenElement(); 
    
    		newelem->tagesproduktion = val; 
    		strcpy(newelem->datum, dat); 
    		first = newelem; 
    
    		if(last != NULL)
    		{	
    			last = newelem;
    		}
    	}
    
    int removeElements(int val) // Element mit bestimmten Wert löschen
    {		
    	ListenElement *current;	
    	ListenElement *prev, *freigabe;
    	int counter = 0;				
    
    	if(first==NULL)	
    		return 0;
    
    	current = first;		
    	prev = first;		
    
    	while(current!=NULL)	
    	{
    		if(current->tagesproduktion==val) // hier Fehlermeldung !!!	
    		{
    			if(current ==first)		
    			{
    				first = current->next;	
    
    				if(last == current)		
    					last = NULL;			
    			}								
    
    			else							
    			{
    				prev->next = current->next;
    
    				if(last == current)	
    					last = prev;		
    			}
    
    			counter++;						
    			freigabe = current;
    			current = current->next;			
    			delete freigabe;				
    		}
    		else 
    		{
    			prev = current;
    			current = current->next;
    		}
    	}
    	return counter;
    }
    
    };
    
    int main()
    {	
    	Produktionsliste l; 
    	l.insert(4,"12.01.2009");
    	l.insert(1,"13.01.2009");
    	l.insert(5,"asdfasf");
    	l.insert(1,"12.01.2008");
    	l.insert(4,"2009");
    
    	l.removeElements(4);
    
    	cin.get();
    	return 0;
    }
    

    //Edit: Code Tag



  • Hallo,

    Verwende bitte die Code Tags das macht das deutlich leserlicher.
    Das hier

    strncpy(datum,dat,12);
    

    ist schonmal falsch, da datum ja nur Platz für 11 Zeichen hat.



  • Da hast du recht Danke 🙂
    Hier noch einmal der Code:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class ListenElement
    {
    
    private:
    	int tagesproduktion;
    	char datum[11];
    	ListenElement *next;
    
    public:
    	ListenElement(){} 
    	ListenElement(int tagesp, char dat[], ListenElement el)
    	{
    		tagesproduktion = tagesp;
    		strncpy(datum,dat,11);
    		next = &el;
    	}
    
    	friend class Produktionsliste;
    
    };
    
    class Produktionsliste
    {
    private:
    	ListenElement *first, *last;
    
    public:
    	Produktionsliste()
    	{
    		first = NULL;
    		last = NULL;
    	}
    
    	void insert(int val, char dat [])
    	{
    		ListenElement *newelem = new ListenElement(); 
    
    		newelem->tagesproduktion = val; 
    		strcpy(newelem->datum, dat); 
    		first = newelem; 
    
    		if(last != NULL)
    		{	
    			last = newelem;
    		}
    	}
    
    int removeElements(int val)
    {		
    	ListenElement *current;	
    	ListenElement *prev, *freigabe;
    	int counter = 0;				
    
    	if(first==NULL)	
    		return 0;
    
    	current = first;		
    	prev = first;		
    
    	while(current!=NULL)	
    	{
    		if(current->tagesproduktion==val)	
    		{
    			if(current ==first)		
    			{
    				first = current->next;	
    
    				if(last == current)		
    					last = NULL;			
    			}								
    
    			else							
    			{
    				prev->next = current->next;
    
    				if(last == current)	
    					last = prev;		
    			}
    
    			counter++;						
    			freigabe = current;
    			current = current->next;			
    			delete freigabe;				
    		}
    		else 
    		{
    			prev = current;
    			current = current->next;
    		}
    	}
    	return counter;
    }
    
    };
    
    int main()
    {	
    	Produktionsliste l; 
    	l.insert(4,"12.01.2009");
    	l.insert(1,"13.01.2009");
    	l.insert(5,"asdfasf");
    	l.insert(1,"12.01.2008");
    	l.insert(4,"2009");
    
    	l.removeElements(4);
    
    	cin.get();
    	return 0;
    }
    


  • Stephan88 schrieb:

    ...

    1. Bitte verwende die Code-Tags für deinen Code ([cpp ]/*hier den Code rein*/[/cpp ] - Ohne die Leerzeichen in den cpp-Tags).

    Stephan88 schrieb:

    Bekomme beim Compilieren immer die Fehlermedlung: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0xcdcdcdcd. Hab mich schon mal erkundigt das diese Fehlermeldung häufig bei Überschreitung von Speicherbereich kommt.

    Ich würde noch allgemeiner sagen: Dieser Fehler kommt immer wenn ein Programm in einen Speicherbereich zugreifen will, der nicht für dieses reserviert ist...

    2. Normalerweise trennt man Deklaration (Header; z.B. *.h) und Definition (Source; z.B. *.cpp), gewöhn dir bitte das using namespace gleich für die Deklaration ab.
    3. Ich würde statt C-Strings die C++ Stringklasse verwenden, zudem fehlt in deinem Programm auch noch das include der C-Bibliothek für die Stringbehandlung (kann indirekt durch #include <string> eingebunden sein, richtiger wäre aber wegen strncpy und Co. <cstring> wenn man die C-Funktionen nutzt)...

    [cpp]
    #include <iostream>
    #include <string>

    using namespace std;

    class ListenElement
    {
    //...
    public:
    // <DIES IST EINE KOPIE!>
    ListenElement(/.../, ListenElement element) //Konstruktor
    {
    //...
    next = ⪙ // Hier weist du den Zeiger einer nur lokal vorhandenen
    // Kopie zu!
    }
    };
    [/cpp]

    4. Objekte solltest du niemals als Kopie übergeben, lieber als konstante Referenz.

    //                     <NUN WIRD KEINE KOPIE ERZEUGT>
    ListenElement(/*...*/, ListenElement const & element)
    

    P.S: Des weiteren:
    Du solltest mal nach Initialisierungslisten suchen (Im Zusammenhang mit dem Konstruktor)... UND niemals etwas uninitialisiert lassen (Dein Standardkonstruktor ist so ein schlechtes Beispiel).



  • @ asc

    Trenne Deklaration und Definition normalerweise auch.

    Warum soll ich

    using namespace std;
    

    nicht deklarieren ?

    Danke



  • Weil das den Sinn von dem Namespace zerstört, und weiterhin zur globalisierung und somit zu Namenskonflikten kommen kann.

    Wäre es nicht langsam an der Zeit das wir das auch mit ins FAQ aufnehmen?



  • Hat jemand eine Lösung für den eigentlichen Fehler gefunden ?



  • Stephan88 schrieb:

    Hat jemand eine Lösung für den eigentlichen Fehler gefunden ?

    Ist jetzt schwierig zu sagen, aber versuch einmal die inserts zu verringern und dann mit dem Debugger zu schauen, wo genau etwas falsch läuft.
    Ich würde einmal darauf tippen, dass du hier:

    counter++;                       
                freigabe = current;
                current = current->next;           
                delete freigabe;
    

    ein Problem hast und current->next dir wieder den Zeiger zurückgibt, der auch von current bereits enthalten wird und danach gibst du den frei und schon hast du einen Zeiger, der auf einen ungültigen Bereich zeigt. Und das kann so einen Fehler auslösen.



  • Stephan88 schrieb:

    Hat jemand eine Lösung für den eigentlichen Fehler gefunden ?

    Also einen potentiellen Fehler habe ich schon angemerkt. Das du mit Zeigern arbeitest, die auf nichts gültiges zeigen (ListenElement::next zeigt wegen Kopie nicht nur während des Konstruktors auf einen gültigen Bereich). Deinen Gesamtcode werde ich aber erst einmal nicht analysieren.


Anmelden zum Antworten