malloc() belegt Speicherbereiche doppelt - warum?



  • Bin etwas verwirrt, vielleicht blickt einer von Euch durch ...

    In meinem Projekt liegen momentan zwei dynamische Listen, in der ersten werden die Bereiche angelegt, auf die ein Touchscreen reagieren soll (TouchWatchList). Wird ein aktiver Bereich gedrückt, sollen aus dieser Liste Pointer auf Funktion und Wert als Event in die zweite dynamische Liste (EventList) eingetragen werden.

    Datei touch.c

    static struct TouchWatch **TouchWatchList = NULL;	// Touchlist
    
    // ...
    
    if (event_list_entry((TouchWatchList[i]->Funktion), (TouchWatchList[i]->Wert)))
    {	
    	i=touchentries;			// erster Bereich gefunden, Überprüfung beenden
    	listphase = 0;			// Neustart
    }
    else show_fatal_error(5);
    

    Bis dahin klappt alles, aber beim Anlegen des Events legt malloc() wieder auf dem Basepointer von TouchWatchList los:

    Datei events.c

    static struct event **EventList = NULL;	// Events- List
    
    // ...
    
    // ********************************************
    // *******  neuen event in Liste eintragen  ***
    // ********************************************
    char event_list_entry(	pFunc funktion_n, void *wert_n)
    {
    	struct event *new_entry = NULL;
    
    	new_entry = event_new(funktion_n, wert_n);
    	if (new_entry)	
    	{
    		if (events) realloc(EventList, ++events * sizeof(struct event*));
    		else EventList = malloc( ++events * sizeof(struct event*));
    		if (EventList)
    		{
    			EventList[events-1] = new_entry;
    		}
    		else show_fatal_error(1);
    	}
    	return(events); 
    }
    // **********************************
    // ******* neuen event anlegen ******
    // **********************************
    struct event *event_new(pFunc funktion_n, void * wert_n)
    {
    	struct event *new_event = NULL;
    		new_event = malloc(sizeof(struct event));
    /* new_event zeigt nun dummerweise auf TouchWatchList - warum? */
    	if (new_event)
    	{
    		new_event->Funktion = funktion_n;
    		new_event->Wert = wert_n;
    	}
    	else show_fatal_error(1);
    	return (new_event);
    };
    

    event_new() wird ja durch event_list_entry() aufgerufen, malloc() liefert aber den Pointer auf die gleiche Adresse wie TouchWatchList zurück, damit hat man spätestens beim zweiten Durchlauf ein heilloses Heap- Durcheinander mit passendem Crash 👎 - was mache ich falsch?

    Danke für's Kopf- schiefhalten, ich weiß nimmer weiter!



  • Wie baust du deine TouchWatchList auf?



  • AJ schrieb:

    Wie baust du deine TouchWatchList auf?

    Ich mache im Prinzip genau dasselbe, wollte euch nur ein bisserl source ersparen:

    Datei touch.c:

    // ************************************************
    // ****** neuen Überwachungsbereich anlegen *******
    // ************************************************
    struct TouchWatch *touch_watch_new(int x0_n, int y0_n, int x1_n, int y1_n, int range_x_n, int range_y_n, pFunc Funktion_n, char *Wert_n)
    {
    // Konstruktorfunktion implement
    
    	struct TouchWatch *new_watch = NULL;
    		new_watch = malloc(sizeof(struct TouchWatch));
    	if (new_watch)
    	{
    		new_watch->x0 = x0_n;
    		new_watch->y0 = y0_n;
    		new_watch->x1 = x1_n;
    		new_watch->y1 = y1_n;
    		new_watch->range_x = range_x_n;
    		new_watch->range_y = range_y_n;
    		new_watch->Wert = Wert_n;
    		new_watch->Funktion = Funktion_n;
    	}
    	else show_fatal_error(1);
    		return(new_watch);
    }
    
    static struct TouchWatch **TouchWatchList = NULL;	// Touchlist
    static char	touchentries = 0;
    
    // ****************************************************************
    // ****** Touchlisteintrag erzeugen *******************************
    // ****************************************************************
    char touch_list_entry(	int x0_n,				// neuer Eintrag
    							int y0_n,
    							int x1_n,
    							int y1_n,
    							int range_x_n,
    							int range_y_n,
    							pFunc Funktion_n,	// pFunc = pointer auf funktion(void *)
    							void *Wert_n )
    {
    	struct TouchWatch *new_entry = NULL;
    
    	new_entry = touch_watch_new(x0_n, y0_n, x1_n, y1_n, range_x_n, range_y_n, Funktion_n, Wert_n);
    	if (new_entry)	
    	{
    		if (touchentries) realloc(TouchWatchList, ++touchentries * sizeof(struct TouchWatch*));
    		else TouchWatchList = malloc( ++touchentries * sizeof(struct TouchWatch*));
    		if (TouchWatchList)
    		{
    			TouchWatchList[touchentries-1] = new_entry;
    		}
    		else show_fatal_error(5);
    	}
    	return(touchentries); // else return (0);
    }
    

    Der Vollständigkeit halber noch ein Auszug aus der main(), wo ich zwei Einträge anlege:

    if (touch_list_entry(160,0,LcdxLines_1,LcdyLines_1,LcdxLines_1,LcdyLines_1,&teste2,&twelve_i))
    touch_watch_start();
    

    Es kracht übrigens wirklich nur bei event_new(), die Pointer der EventList legt er brav woanders ab.

    Danke nochmals!



  • Auf jeden Fall darfst du nicht den Rückgabewert von realloc ignorieren.



  • ign0rant schrieb:

    Auf jeden Fall darfst du nicht den Rückgabewert von realloc ignorieren.

    Aaaargh! 😡 Klar doch, das war's!
    Danke, und wieder ein Beispiel, wie blind man sein kann, wenn man immer nur dieselben Zeilen angafft 😕
    Jetzt geh' ich erstmal ins Eckchen, um mich gepflegt zu schämen ... 😞



  • tritt der Fehler bei der ersten Ausfuehrung auf oder erst spaeter?



  • leo aka qsch schrieb:

    tritt der Fehler bei der ersten Ausfuehrung auf oder erst spaeter?

    Das Problem ist ja schon gelöst, Erklärung zur Nachreiche:
    Ich habe zwei "Watches" in der TouchWatchList angelegt, beim zweiten aber den von Realloc gelieferten Pointer nicht übernommen und damit verpaßt, daß TouchWatchList auf einen nunmehr freien Bereich verweist (falsch!!). Beim Anlegen des ersten Events kriege ich den ersten freien Speicher - und der liegt genau dort, wo vorher die TouchWatchList lag (ist aber keine allgemeingültige Weisheit, könnte je nach Compiler/OS auch irgendwo anders liegen).
    So, lustigerweise hat man überhaupt keine Probleme, wenn man TouchList und EventList separat durchtestet (aber vermutlich auch nur mit genau diesem Compiler), und weil man einen Fehler, den man nicht erkennt, gerne durch Copy&Paste vermehrt, fällt man zu spät auf die Schnauze und schaut sich vermeintlich richtige Dinge nicht mehr an.
    Richtigerweise hätte es heißen müssen:

    if (touchentries) TouchWatchList = realloc(TouchWatchList, ++touchentries * sizeof(struct TouchWatch*));
    		else TouchWatchList = malloc( ++touchentries * sizeof(struct TouchWatch*));
    

    und natürlich auch:

    if (events) EventList = realloc(EventList, ++events * sizeof(struct event*));
    		else EventList = malloc( ++events * sizeof(struct event*));
    

    Alle Klarheiten beseitigt? 😉


Anmelden zum Antworten