falscherptr problem



  • Hallo ... ich komme mal wieder nicht dahinter warum mir mein Kompiler falscherptr zurück gibt bzw ich angeblich auf einen falschen Speicherbereich zugreife :/...

    meine Struktur:

    struct verleih;
    
    struct dvd{
    	int dvdnummer;
    	char dvdname[64];
    };
    
    struct buch{
    	int buchnummer;
    	char name[64];
    	char autor[64];
    	verleih *letzteAusleihe;//
    	//...
    };
    
    struct artikel{
    	int artikelnummer;
    	int artikelart;//0 ist nicht definiert 1 DvD 2 Buch
    
    	union daten{
    		dvd * ptrDvd;
    		buch * ptrBuch;
    	}artikeldaten;
    	verleih * ptrAusleihe;
    };
    
    struct kunde{
    int kundennummer;
    char name[64];
    //...
    };
    
    struct verleih{
    buch *vbuch[10];
    kunde *vkunde;
    //...
    };
    

    Dazu mein Code der meine Artikel in der "Bibliothek" anzeigen soll:

    void artikel_anzeigen()
    {
    	int i;
    
    	for (i=0; i<10; i++)
    	{
    		if(neuerartikel[i].artikeldaten.ptrBuch->name != '\0' )
    			printf("Buchname:'%s'\n",neuerartikel[i].artikeldaten.ptrBuch->name);
    		else if (neuerartikel[i].artikeldaten.ptrBuch->name != '\0' && i<1)
    		{
    			printf("Keine Buecher in der Bibliothek \n");
    			break;
    		}
    	}
    }
    

    Ich muss dazu sagen das ich frisch bin im Thema Pointer und wohlmöglich das Problem nur ein kleines ist welches ich trotzdem nicht herausfinde ^^

    also als Fehlermeldung kommt das ich auf einen Falschen Speicherbereich zeige!? falscher ptr wenn ich mir die zB.

    scanf("%d",&neuerartikel[i].artikeldaten.ptrBuch->buchnummer);
    

    anschaue.

    Danke schonmal



  • starte es im debugger und mach 'nen breakpoint in die zeile. ich wette 'ptrBuch' zeigt sonstwohin.
    btw, hat msvc nicht immer 'schlechtes ptr' gesagt?
    🙂



  • +fricky schrieb:

    starte es im debugger und mach 'nen breakpoint in die zeile. ich wette 'ptrBuch' zeigt sonstwohin.
    btw, hat msvc nicht immer 'schlechtes ptr' gesagt?
    🙂

    schon durchgedebugt so gut ich es konnte... und der Fehler taucht ab Zeile 8 in dem 2. Codebeispiel auf. Promptmeldung Ungültiger Speicherbereichszugriff... ok schon klar das dann wohl irgendwas (ptrBuch wies aussieht sonstwohin zeigt. nur was tu ich dagegen? eigentlich zeigt er doch auf die Struktur Buch und soll dort den Namen holen ?!



  • Virokams schrieb:

    eigentlich zeigt er doch auf die Struktur Buch und soll dort den Namen holen ?!

    Welche Struktur Buch denn? Wenn der Zeiger auf eine solche zeigen soll, dann musst du diese Struktur anlegen und den Zeiger darauf verweisen lassen.

    Nur weil du einen Zettel mit einer Adresse hast, steht da noch lange kein Haus.



  • Zeig mal die Stelle, wo du ptrBuch eine Adresse zuweist.



  • Oh Oh ... kann es sein das das der Fehler ist? Ich weiße dem ptr keinen Wert zu?

    also wie gesagt bin ja noch Frisch in dem Thema und ich weiß jetzt nicht genau wie ich das bewerkstelligen muss das ich dem ptrBuch einen Wert zuweise... ich dachte das wenn ptrBuch->name zeigt das er dann den Wert aus Name nimmt?

    Meine Struktur Buch:

    struct buch{
    	int buchnummer;
    	char name[64];
    	char autor[64];
    	verleih *letzteAusleihe;//
    	//...
    };
    

    Dort steckt ja name drinne und so dachte ich das :

    neuerartikel[i].artikeldaten.ptrBuch->name
    

    dann halt auf den Buchnamen zeigt ... sich den Buchnamen rausholt ... Falsch gedacht?



  • Nein, das wäre Münchhausen- Methode, sich an den eigenen Haaren aus dem Sumpf zu ziehen.
    Du mußt jede Adresse initialisieren. Üblicherweise erhältst Du da den Pointer per malloc.
    Also struct Buch alleine ist ja nur die Beschreibung, wie das aussieht, aber noch kein echter Speicher, ebensowenig wie der Pointer darauf.



  • Ja, falsch gedacht! 😉

    Wenn du einen Zeiger vom Typ buch erzeugst, dann ist das halt erstmal nur ein Zeiger vom Typ buch. Das heißt aber noch nicht, dass er auch auf gültigen Speicher zeigt.

    buch MeinBuch;
    buch *pBuch=&MeinBuch;  //hier würde pBuch auf MeinBuch zeigen und du könntest mit pBuch->name auf das Element zugreifen. pBuch selbst enthält aber nur die Adresse, nichts weiter.
    
    buch *pBuch2;  //dieser Zeiger zeigt noch nirgendwo hin.
    

    In deinem Fall würde ich mal sagen, dass ein Zeiger unnötig ist, oder? erzeuge einfach eine normale Instanz der Struktur buch in artikel.





  • _matze schrieb:

    Ein wenig Lektüre zum Thema gibt's hier:

    http://www.c-plusplus.net/forum/viewtopic-var-t-is-124532-and-sid-is-d52fd8c501b2fd34da0da8c5f0017c81.html

    Werd ich mir mal antun heute ABend "also die Lektüre 😉 " ...

    So also die Deklaration der Struktur hab ich ja (nur nicht mitkopiert):

    buch neuesbuch[10];
    

    jetzt muss also noch der Pointer deklariert werden?

    daten *ptrBuch = &neuesbuch
    

    ?



  • Virokams schrieb:

    buch neuesbuch[10];
    
    daten *ptrBuch = &neuesbuch
    

    ?

    Das dürfte nicht klappen. Wenn, dann so:

    daten *ptrBuch = neuesbuch;
    

    Aber ob das so alles sinnvoll ist...

    Zeig am besten mal ein wenig mehr Code. Konnte z.B. ja keiner ahnen, dass neuesbuch ein Array ist... 😉



  • Virokams schrieb:

    So also die Deklaration der Struktur hab ich ja (nur nicht mitkopiert):

    buch neuesbuch[10];
    

    du müsstest übrigens noch 'struct' davor schreiben. 'buch' ist ja kein typedef bei dir.
    beispiel:

    struct buch
    {
       ...
    };
    
     ...
     buch b; // error
     struct buch b; // so geht's
     ...
    

    🙂



  • +fricky schrieb:

    du müsstest übrigens noch 'struct' davor schreiben. 'buch' ist ja kein typedef bei dir.

    Ist bestimmt mit nem C++-Compiler erstellt...



  • _matze schrieb:

    ...

    Zeig am besten mal ein wenig mehr Code. Konnte z.B. ja keiner ahnen, dass neuesbuch ein Array ist... 😉

    Ok also hier die ganzen relevanten Code ausschnitte:

    Struct.h:

    #pragma once
    
    #include <stdio.h>
    #include <tchar.h>
    #include "stdafx.h"
    
    struct verleih;
    
    struct dvd{
    	int dvdnummer;
    	char dvdname[64];
    };
    
    struct buch{
    	int buchnummer;
    	char name[64];
    	char autor[64];
    	verleih *letzteAusleihe;//
    	//...
    };
    
    struct artikel{
    	int artikelnummer;
    	int artikelart;//0 ist nicht definiert 1 DvD 2 Buch
    
    	union daten{
    		dvd * ptrDvd;
    		buch * ptrBuch;
    	}artikeldaten;
    	verleih * ptrAusleihe;
    };
    
    struct kunde{
    int kundennummer;
    char name[64];
    //...
    };
    
    struct verleih{
    buch *vbuch[10];
    kunde *vkunde;
    //...
    };
    

    artikel.cpp:

    #include "stdafx.h"
    #include "struct.h"
    #include <stdio.h>
    #include <string.h>
    #include "artikel.h"
    
    struct buch neuesbuch[10];
    struct dvd neuedvd[10];
    struct artikel neuerartikel[20] = { 0 };
    
    void clearbuf()
    {
        setvbuf(stdin,NULL,_IONBF,0);
        setvbuf(stdin,NULL,_IOFBF,BUFSIZ);
    } 
    
    void artikel_anzeigen()
    {
    	int i;
    	neuerartikel[0].artikeldaten.ptrBuch = NULL;
    
    	for (i=0; i<10; i++)
    	{
    		if(neuerartikel[i].artikeldaten.ptrBuch->name != '\0' )
    			printf("Buchname:'%s'\n",neuerartikel[i].artikeldaten.ptrBuch->name);
    		else if (neuerartikel[i].artikeldaten.ptrBuch->name != '\0' && i<1)
    		{
    			printf("Keine Buecher in der Bibliothek \n");
    			break;
    		}
    	}
    }
    
    //Buchdeklaration
    void Testbuchdaten()
    {
    	strcpy(neuesbuch[0].name,"Harry Potter");
    	strcpy(neuesbuch[0].autor,"Joanne K. Rowling");
    	neuesbuch[0].buchnummer = 0;
    
    //....... viele mehr
    
    }
    

    mehr ist eigentlich nicht wichtig würde ich sagen.
    Wenn ich erstmal weiß wo der Fehler bei der Anzeige der Artikel ist wird mir das erstellen von Artikeln vielleicht auch klarer 🙂

    als zusatz Artikel_erstellen():

    void artikel_anlegen()
    {
    	int i = 0;
    	int j = 0;
    	int z = 0;	
    
    	for (j = 0; j>20; j++)//Artikelnummer bestimmen ... leeren platz finden
    	{
    		if ( neuerartikel[j].artikeldaten.ptrBuch->name != '\0' )
    		{
    			neuerartikel[j].artikelnummer = j;
    			break;
    		}
    	}
    
    	printf("Welche Art von Artikel soll hinzugefuegt werden?\n1 DvD\n2 Buch\n");
    	scanf("%d",&neuerartikel[neuerartikel[j].artikelnummer].artikelart);
    
    	if ( neuerartikel[neuerartikel[j].artikelnummer].artikelart == 1 )
    	{
    		printf("bla");
    		return;
    		//DvD anlegen
    	}
    	else if ( neuerartikel[neuerartikel[j].artikelnummer].artikelart == 2 )
    	{
    
    		for(i=0; i<10; i++)
    		{
    			if ( neuerartikel[i].artikeldaten.ptrBuch->name[0] == '\0')
    			{	 
    				printf("Bitte Buchnummer angeben:\n");//Buchnummer
    				scanf("%d",&neuerartikel[i].artikeldaten.ptrBuch->buchnummer);
    
    				clearbuf(); 
    				printf("Bitte Buchnamen eingeben:\n");//Buchname
    				gets(neuerartikel[i].artikeldaten.ptrBuch->name);
    
    				clearbuf();
    				printf("Bitte Buchautor angeben:\n");//Buchautor
    				gets(neuerartikel[i].artikeldaten.ptrBuch->autor);
    
    				for(int j=0; j<i; j++)//Durchlauf der Buchnummern
    				{	//Keine Buchnummer darf doppelt sein!
    					if(neuerartikel[i].artikeldaten.ptrBuch->name == neuerartikel[j].artikeldaten.ptrBuch->name)
    					{
    						printf("Die Buchnummer ist schon in verwendung. ");//
    						neuerartikel[i].artikeldaten.ptrBuch->autor[j] = '\0';
    						neuerartikel[i].artikeldaten.ptrBuch->name[j] = '\0';
    						neuerartikel[i].artikeldaten.ptrBuch->buchnummer = '\0';
    						z=1;
    						break;
    					}
    				}
    				if(z>0)//Z>0 wenn Buchnummer vorhanden dann wird kein Buch ausgeliehen 
    				{
    					printf("Es wurde kein Buch hinzugefuegt!\n");
    					break;
    				}
    				else//Buch wird hinzugefügt
    				{
    					printf("BNr:%d Name:'%s' von '%s' wurde angelegt!\n"); 
    					getchar();
    					break;
    				}
    			}
    		}
    		// Buch anlegen
    	}
    	else if ( neuerartikel[neuerartikel[j].artikelnummer].artikelart > 2 || neuerartikel[neuerartikel[j].artikelnummer].artikelart < 1 )
    	{
    		printf("Nichtdefinierte Eingabe! Bitte 1 fuer DvD oder 2 fuer Buch eingeben!");
    		return;
    	}
    }
    


  • Ein paar grundlegende Tipps:

    Deine structs global in struct.h anzulegen, halte ich nicht für so gut. Warum sind das nicht z.B. lokale Variablen der main, die du dann als Parameter an die Funktionen übergibst, die auch was damit machen?

    buch sollte einfach ein Member von artikel sein. Ich verstehe nicht ganz, warum ein neuer Artikel auf ein Element eines ansonsten unabhängigen buch-Arrays zeigen sollte. Mach es doch einfach so, dass jeder Artikel halt eine Struktur enthält, in der du Namen, Autor usw. ablegst.

    Wenn du einen neuen Artikel anlegen willst, dann ist diese Schleife, um festzustellen, welches Element noch nocht gefüllt wurde, nicht so optimal. Halte z.B. einfach in einer Variablen fest, wieviele Elemente bereits hinzugefügt wurden.

    Ich würde mich ärgern, wenn ich ständig komplette Bücher eingeben würde, nur um im Anschluss dann gesagt zu bekommen, dass die Buchnummer (also die erste Eingabe) falsch war, weil schon vorhanden, und alle Eingaben verworfen werden. 😉 Außerdem überschreibst du alle gemachten Eingaben dann mit 0. Sinnvoller wäre es, es gar nicht soweit kommen zu lassen. Eingabe der Nummer in eine temporäre Variable, wenn gültig dann weitermachen. Noch sinnvoller wäre es, die Buchnummer automatisch fortlaufend zu vergeben (es sein denn, du willst, dass Lücken entstehen dürfen).

    Sowas hier

    for (j = 0; j>20; j++)
    

    geht nicht. In die Schleife springt er nie rein. j wird mit 0 initialisiert, die Bedingung ist aber "mache weiter, solange j>20 ist". Sie ist also nie erfüllt. Du meinst vermutlich j<20.

    Es macht ein wenig den Eindruck, dass du versuchst, all deine Ideen in einem Rutsch ins Programm zu quetschen, und dabei vielleicht ein klein wenig die Übersicht verlierst. 🙂 Versuche einfach, strukturierter zu programmieren und dich Stück für Stück 'ranzutasten. Z.B. könntest du erst mal mit den Büchern anfangen. Und wenn das steht und perfekt läuft, dann kannst du die DVDs und das ganze Verleihen hinzufügen.



  • ^^und falls das keine übung für structs und pointer-auf-structs, etc. sein soll, sondern ein programm, dass irgendwann mal wirklich benutzt wird, dann nimm 'ne richtige datenbank dafür, mySQL oder sowas.
    🙂



  • +fricky schrieb:

    ^^und falls das keine übung für structs und pointer-auf-structs,

    Glaube ich schon, daher...

    +fricky schrieb:

    nimm 'ne richtige datenbank dafür, mySQL oder sowas.

    Nö, lieber erstmal nicht. Denn wenn das erstmal alles steht, hat er einiges kapiert. Dann ist man schlauer und kann immer noch über eine "richtige" Lösung mit 'ner Datenbank nachdenken. 🕶



  • jau die for schleife ist schon korrigiert... natürlich hab ich mich verschrieben.

    also deine Tipps sind grundlägend natürlich total richtig. "Problem" an der Sache ist das es vorgaben vom Ausbilder sind. also Wenn da jetzt etwas nicht soooo prickelnd ist ... soll es so bleiben weil es meinem Ausbilder grundsätzlich um die Arbeit mit Ptr geht. Ich soll das halt lernen ... übern ... das Programm war ja schon fertig von mir geschrieben... als zusatzübung wurde jetzt noch die Struct Artikel mit der enthaltenen Union gemacht.

    also tut mir leid wenn ich 2 Beiträge später immer noch den "unschönen" Code vorzeigen muss aber ich lasse ihn jetzt erstmal so wie er ist und versuche nur weiter mit Ptr was zu machen (Wie auch meine Frage war wo denn jetzt mein Fehler liegt das er mir schlechterptr anzeigt... bzw das ich auf einen fremden Speicher zugreife).

    also komme ich nochmal zurück und sage schonmal Danke natürlich nehme ich mir die Tipps zu herzen :)!

    wenn ich es also schaffe den ptr vernünftig auf einen Speicher zu deklarieren dürfte kein fehler kommen das er auf einen Fremden Speicher zugreift?



  • Virokams schrieb:

    wenn ich es also schaffe den ptr vernünftig auf einen Speicher zu deklarieren dürfte kein fehler kommen das er auf einen Fremden Speicher zugreift?

    Jo! Entweder, du weist dem Pointer eine gültige Adresse zu (von einer Variablen, die bereits existiert, wie in meinem Beispiel vorhin), oder du forderst mit malloc speicher an, in den du dann schreiben darfst. In letzterem Fall darfst du aber nicht das free vergessen, dass den Speicher wieder freigibt (sonst produzierst du ein Speicherleck).



  • gut soweit verstanden ... zur Syntax:

    union daten *ptrBuch = NULL;

    geht nicht...

    neuerartikel[0].artikeldaten.ptrBuch = NULL;

    hatte ich auch probiert... geht auch nicht...

    hääh? -.-


Log in to reply