wie eine verkette liste richtig löschen

Hi, ich mal wieder mit ner dau frage:

ich möchte folgende liste zur gänze löschen, und den belegten speicher wieder frei bekommen. Wie mache ich das richtig?

// structure of my list
typedef struct a_sensor{
  unsigned long id; // decimal RC code
  String name; // readable name
  byte level;  // 0=always on, 1=nightmode, 2=full armed
  unsigned long lasttime;
  boolean      hastriggered;
  byte action;
  unsigned int timedelay;
  a_sensor* nextsensor;
} a_sensor;


// root is the start of my list
a_sensor *root;


// this is used to add an new entry to my lit
void addSensor(unsigned long id, String name, byte level, byte action, unsigned int timedelay) {
  a_sensor *s = new a_sensor;
  a_sensor *p = root;
  s->id = id;
  s->name = name;
  s->level = level;
  s->lasttime = 0;
  s->hastriggered = false;
  s->action = action;
  s->timedelay = timedelay;
  s->nextsensor = NULL; // end of list;
  
  if(root == NULL) // list is empty
  {
    root = s; // put this sensor on top of list so it is the first
  } else { // there are already at least one other snesor in the list, so append
    while (p->nextsensor != NULL) // search for the end of the list
       p = p->nextsensor;
      
    p->nextsensor = s;
  }
}




void setup()
{

  // ----- freier speicher an dieser stelle gemessen ------

  // add two entries to the list
  addSensor(12345,"TEST1",1,1,1);
  addSensor(67890,"TEST2",2,1,1);


 // mow lets clear the list and free used memory
 free(root);

  // ----- freier speicher am ende gemessen ------

}

Ich habe es - ganz unbedarft - mal mit free(root) probiert. Die liste ist zwar weg, aber es wird nicht der genaze belegte speicher wieder frei gegeben. Dann habe ich es recursiv versucht, und jedes einzelne listen-Event gelöscht. aber dabei komme ich am ende auf das selbe Ergebnis. Es wird zwar ein teil des speichers frei, aber ich komme nicht annähernd auf den Anfangswert.

Was mache ich da falsch?

GLG und VIELEN Dank für eure Hilfe!

free(root) löscht nur die Wurzel. Am einfachsten ist es du fängst bei der Wurzel an, speicherst den aktuellen next-Knoten zwischen, löschst den aktuellen Knoten, gehst auf den next-Knoten, usw. Den next-Knoten muss man zwischenspeichern, da der Zeiger auch gelöscht wird wenn man den aktuellen Knoten löscht.

Dazu braucht man keine Rekursion. Rekursion ist bei Bäumen sehr schön, aber Listen kann man auch einfach iterativ abarbeiten.

:smiley: also war mein Ansatz mit free() ja garnicht so weit daneben...außer dass ich wieder mal die umständlichste Methode (recuriv) gefunden habe lol

Umständlich ist es nicht. Im Gegenteil. Mit Rekursion hat man oft kleineren Quelltext. Aber die Funktionsaufrufe kosten halt auch Speicher auf dem Stack. Bei kleinen Listen ist das egal, aber dir sollten die Nachteile klar sein wenn du das verwendest.

Wie gesagt, Baum-Traversierung ist das Paradebeispiel für Rekursion im Bereich Datenstrukturen:

Das artet iterativ richtig in Arbeit aus. Liegt aber daran, dass da jeder Knoten bis zu zwei Nachfolger hat was bei einer Liste nicht der Fall ist.

hi,

Liegt aber daran, dass da jeder Knoten bis zu zwei Nachfolger hat was bei einer Liste nicht der Fall ist.

wieso zwei? in einem baum ist das ja nicht eingeschränkt. siehe ein dateisystem oder XML.

aber irgendwie ist infantilos problem ja so oder so nicht gelöst. wenn's mit free beim rekursiven ansatz nicht klappt, wieso sollte es dann iterativ funktionieren?

gruß stefan

Willst du die Liste immer komplett löschen, oder auch nur einzelne Elemente rausnehmen ?
Wenn du diese Einzel-Lösch Funktion brauchst, müsstest du auch den jweiligen Vorgänger eines Elements haben, um den Rest der Liste umzuketten.
Dann ist übrigens die Funktion "Alles Löschen" nur ein "Solange einzelne Elemente löschen, bis root == NULL"

Mal ganz abgesehen davon, dass dynamischer Speicher bei Controllern mit ein paar Byte RAM oft nur Firlefanz ist. :wink:

Eisebaer:
wieso zwei? in einem baum ist das ja nicht eingeschränkt. siehe ein dateisystem oder XML.

Ich hätte sagen sollen "Binärbaum". Gibt natürlich auch bei den klassischen Datenstrukturen noch Dinge wie B-Bäume.

aber irgendwie ist infantilos problem ja so oder so nicht gelöst. wenn's mit free beim rekursiven ansatz nicht klappt, wieso sollte es dann iterativ funktionieren?

Vielleicht. Da müsste man mal den Code sehen was er wirklich gemacht hat.

Also das ist der sketch. Ich sitze gerade in der Firma und musste ihn jetzt "nachschreiben" (ist also ungetestet, e.v. Tippfehler).
Bin für jede(!) verbesserung/Vereinfachung offen UND DANKBAR!!!!

Ich will eben meine Alarmanlage/Automatisation eben nicht immer neu starten müssen, wenn ich die "conifg" (Zeitschaltungen, Sensoren,etc.) ändere.

#include <EEPROM.h>
#include <EEPROMAnything.h>

const int EEPROM_START = 32;

typedef struct a_sensor{
  unsigned long id; // decimal RC code
  String name; // readable name
  byte level;  // 0=always on, 1=nightmode, 2=full armed
  unsigned long lasttime;
  boolean      hastriggered;
  byte action;
  unsigned int timedelay;
  a_sensor* nextsensor;
} a_sensor;



// --------------------------------------
// alarm state definitions
// --------------------------------------
const byte arm = 1;
const byte disarm = 2;
const byte alert = 3;
const byte transmit = 4;
const byte timed = 5;



  unsigned long id = 123456; // decimal RC code
  String name = "KARL"; // readable name
  byte level = 1;  // 0=always on, 1=nightmode, 2=full armed
  unsigned long lasttime = 2;
  boolean      hastriggered = true;
  byte action = 0;
  unsigned int timedelay = 100;
  
  
a_sensor *root;


void SaveSetup()
{
   long unsigned int pos = EEPROM_START;
  
    a_sensor *tmp = root;
  
  do
  {
 
    EEPROM_writeAnything(pos, tmp->id);
    pos += sizeof(tmp->id);
    int l = tmp->name.length();
    for(int i=0; i<=l && i<60; i++)
    {
      EEPROM_writeAnything(pos+i, tmp->name[i]);
	// ich denke, hier sollte ich irgendwie auf "\0" prüfen und ggf. früher aussteigen?
    }
    char endc = '\0';
    EEPROM_writeAnything(pos+l, endc);
    pos += l + sizeof(endc); //sizeof(tmp->name);
    EEPROM_writeAnything(pos, tmp->level);
    pos += sizeof(tmp->level);
    EEPROM_writeAnything(pos, tmp->action);
    pos += sizeof(tmp->action);
    EEPROM_writeAnything(pos, tmp->timedelay);
    pos += sizeof(tmp->timedelay);
    byte n = 0;
    if(tmp->nextsensor != NULL) {
      n = 1;
    }
    EEPROM_writeAnything(pos, n);
    pos += sizeof(n);
    tmp = tmp->nextsensor;
  } while (tmp != NULL);
}



void LoadSetup()
{
  byte n = 1;
  
  long unsigned int pos = EEPROM_START;
  
  root = NULL;
  
  do
  {
    char buffer[60];
    int i = 0;
    name = "";
    EEPROM_readAnything(pos, id);
    pos += sizeof(id);
    for (i=0 ;i<60; i++)
    {
      EEPROM_readAnything(pos+i,buffer[i]);
      name += buffer[i];
      if (buffer[i] == '\0')
      {
        break;
      }
    }
    pos += i+1;
    EEPROM_readAnything(pos, level);
    pos += sizeof(level);
    EEPROM_readAnything(pos, action);
    pos += sizeof(action);
    EEPROM_readAnything(pos, timedelay);
    pos += sizeof(timedelay);
    EEPROM_readAnything(pos, n);
    pos += sizeof(n);
    
    addSensor(id,name,level,action,timedelay);
       
  } while(n == 1);
}


void InitialiseSettings() {
// Sensors
  addSensor(11111,"ALARMANLAGE EIN(KeyA)",1,arm,1);
  addSensor(22222,"ALARMANLAGE AUS(KeyB)",1,disarm,1);
  addSensor(33333,"NACHTMODUS (D-ON)",2,arm,1);
  addSensor(44444,"NACHTMODUS (D-OFF)",2,disarm,1);  
  
  // add Timers, either ID or name of the event to trigger; the switching-time goes into the delaytime!
  addSensor(55555,"LEDs-ON",0,timed,865);    // 990 = 16*30+30 == 16:30
  addSensor(66666,"LEDs-OFF",0,timed,866);  // 1320 = 22*30 == 22:00
}


//---------------------------------------------------------------------------------------------
// add a new sensor to list
// ---------------------------------------------------------------------------------------------
void addSensor(unsigned long id, String name, byte level, byte action, unsigned int timedelay) {
  a_sensor *s = new a_sensor;
  a_sensor *p = root;
  s->id = id;
  s->name = name;
  s->level = level;
  s->lasttime = 0;
  s->hastriggered = false;
  s->action = action;
  s->timedelay = timedelay;
  s->nextsensor = NULL; // end of list;
    
  if(root == NULL) // list is empty
  {
    root = s; // put this sensor on top of list so it is the first
  } else { // there are already at least one other snesor in the list, so append
    while (p->nextsensor != NULL) // search for the end of the list
       p = p->nextsensor;      
    p->nextsensor = s;
  }
}


void emptylist()
{
  a_sensor *p = root;
  while (root != NULL)
  {
    //fahre ans Ende der liste
    while (p != NULL)
    {
      p = p->nextsensor;
    }
	// lösche den letzen der liste
	free(p);	
	// springe wieder an den anfang der liste
	p = root;
  }
}

int freeRam()
{
  extern int __heap_start, *__brkval;
  int v;
  return(int) & v - ( __brkval == 0 ? (int) & __heap_start : (int) __brkval);
}


void setup()
{
  Serial.begin(9600);
  // zeige freien speicher zu beginn
  Serial.println(freeRam());

  // erzeuge eine snesorliste aus "bsetehenden" werten
  InitialiseSettings();
  // zeige freien speicher mit sensorliste
  Serial.println(freeRam());


  // speichere die aktuelle sensorliste ins eeprom
  SaveSetup();
  // lösche die liste 
  emptylist();

  //zeige freien Speicher nach dem leeren der liste
  Serial.println(freeRam());

 // lade die sensorliste aus dem eeprom
  LoadSetup();
 //zeige freien speicher nach dem laden der liste
  Serial.println(freeRam());
}

void loop()
{
}

Vielen Dank übrigens für all eure Mühen! Ihr seid echt spitze!!!!!!! DANKE!!!

Das ist etwas unsinnig, wenn du die ganze Liste löschen willst. Du löscht immer den letzten Knoten und springst dann wieder zur Wurzel. Obwohl das theoretisch auch gehen sollte.

So könnte es glaube ich gehen:

void emptylist()
{
  a_sensor* current = root;

  while (current != NULL)
  {
      a_sensor* next = current->nextsensor;

      free(current);
      current = next;
  }
}

HI =(
hab es versucht, aber leider funktioniert es nicht...
es wird auch so nur ein kleiner Teil des Speichers freigegeben.

1617.......Speicher am Beginn von Setup()
Initialize / Generate Sensorlist (generiere eine Liste von 4 Sensoren)
1486.....mit 1 Sensor
1438.....mit 2 Sensoren
1394.....mit 3 Sensoren
1349.....mit 4 Sensoren
Saving Sensorlist (speichere die Liste in das eeprom)
1408....Speicher nach dem schreiben ins EEPROM (auch hier geht eigenartigerweise speicher verloren????????)
freeing root / Sensorlist (lösche die Liste mit emptyList())
1306....Speicher nach dem Löschen der Liste (warum werden hier nur 102 freigegeben???)
Loading Sensorlist (lade die Liste aus dem EEPROM)
1229.....mit 1 Sensor
1256.....mit 2 Sensoren
1204....mit 3 Sensoren
1231.....mit 4 Sensoren
finished!

Ich verstehe 2 Sachen nicht:
.) warum werden eben nur die 102byte freigegeben, wo die liste doch 268 groß ist?
.) und was mach ich beim SaveList falsch, dass ich auch hier Speicher verliere???
Ich blick da nicht durch?

im Anhang hab ich den sketch dazugegeben.
Könntet ihr da nochmals einen Blick draufwerfen? DAAAAANKE!

sketch_feb21b.ino (6.1 KB)

infantilo:
Ich verstehe 2 Sachen nicht:
.) warum werden eben nur die 102byte freigegeben, wo die liste doch 268 groß ist?
.) und was mach ich beim SaveList falsch, dass ich auch hier Speicher verliere???
Ich blick da nicht durch?

Dass die in Reply #7 von Dir gepostete Funktion zur Ermittlung des Freien Speichers Dir nicht den gesamten freien RAM-Speicher zurückliefert, ist Dir dabei aber schon klar, oder? Sondern dass diese Funktion nur "den größten freien, zusammenhängenden Speicherblock" auf dem Heap liefert?

Das ist zwar identisch, wenn Du im Sketch OHNE DYNAMISCHE Speicheranforderungen arbeitest. Aber wenn Du den RAM-Speicher fragmentierst und dynamisch freien RAM-Speicher anforderst und wieder freigibst, dann gibt es im RAM außer dem größten freien zusammenhängenden RAM-Speicherblock auch immer noch kleine freie Fragmente, die über eine Memory-Allocation-Liste verwaltet werden und die Du für eine vollständige Speicherangabe noch draufzählen müßtest, wenn sie frei sind.

Was passiert denn, wenn Du Deine Liste mehrfach nacheinander füllst und freigibst, wird dann der Speicher jedesmal weniger? Oder nur beim ersten mal Füllen und Freigeben?

In dem struct ist ein String Objekt enthalten. Das belegt selbst dynamischen Speicher. Es kann sein, dass Probleme verursacht oder zumindest zur Heap Fragmentierung beträgt. Ist aber geraten.

Ich habe hier mal eine beispielhafte und recht rudimentäre C++-Klasse gefunden:
http://tnvbalaji.com/2012/04/04/linkedlist/

Nachdem ich den Code mal für Arduino umgeschrieben hatte und eine irgendwie fehlerhaft verstümmelte for-Schleife wieder mit Sinn gefüllt war, ist das dabei als Listenobjekt-Klasse und Demo-Sketch herausgekommen:

class LinkList
{
private:
      struct Node
      {
        int data;
        Node* link;
      }*p;
 
public:
      LinkList();
      ~LinkList();
 
       void Print();         // Prints the contents of linkedlist
       void Append(int num); // Adds a new node at the end of the linkedlist
       void Delete(int num); // Deletes the specified node from the linkedlist
 
       void AddatBeg(int num);// Adds a new node at the beginning of the linkedlist
       void AddAfter(int c, int num); // Adds a new node after specified number of nodes
       int Count();          // Counts number of nodes present in the linkedlist
 
};
 
LinkList::LinkList()
{
  p = NULL;
}
 
LinkList::~LinkList()
{
  if (p == NULL)
        return;
 
  Node* tmp;
  while(p != NULL)
  {
       tmp = p->link ;
     delete p;
       p = tmp;
  }
}
 
// Prints the contents of linkedlist
void LinkList::Print()
{
  if (p == NULL)
  {
        Serial.print("EMPTY");
        return;
  }
 
  //Traverse
  Node* tmp = p;
  while(tmp != NULL)
  {
       Serial.println(tmp->data);
       tmp = tmp->link ;
  }
}
 
// Adds a new node at the end of the linkedlist
void LinkList::Append(int num)
{
      Node *newNode;
 
      newNode = new Node;
      newNode->data = num;
      newNode->link = NULL;
 
       if(p == NULL)
      {
       //create first node
         p = newNode;
      }
       else
      {
             //Traverse
            Node *tmp = p;
             while(tmp->link != NULL)
            {
                  tmp = tmp->link;
            }
 
             //add node to the end
        tmp->link = newNode;
      }
}
 
// Deletes the specified node from the linkedlist
void LinkList::Delete( int num )
{
   Node *tmp;
 
   tmp = p;
   //If node to be delete is first node
   if( tmp->data == num )
   {
      p = tmp->link;
      delete tmp;
      return;
   }
 
   // traverse list till the last but one node is reached
   Node *tmp2 = tmp;
   while( tmp!=NULL )
   {
      if( tmp->data == num )
      {
         tmp2->link = tmp->link;
         delete tmp;
         return;
      }
 
      tmp2 = tmp;
      tmp = tmp->link;
   }
   Serial.print("\nElement ");Serial.print(num);Serial.print(" not Found.");
}
 
// Adds a new node at the beginning of the linkedlist
void LinkList::AddatBeg(int num)
{
      Node *tmp;
 
       //add new node
      tmp = new Node;
      tmp->data = num;
      tmp->link = p;
      p = tmp;
}
 
//Adds a new node after specified number of nodes
void LinkList::AddAfter(int c, int num)
{
      Node *tmp;
      Node *tmp2;
       int i;
       //Skip to the desired portion
       for( i = 0, tmp = p; i<c;i++)
      {
            tmp = tmp->link;
 
             //if end of linked list is encountered
             if(tmp == NULL)
            {
                  Serial.print("There are less than ");Serial.print(c);Serial.print(" elements");
                   return;
            }
      }
 
       //insert new node
      tmp2 = new Node;
      tmp2->data = num;
      tmp2->link = tmp->link;
      tmp->link = tmp2;
}
 
// Counts number of nodes present in the linkedlist
int LinkList::Count()
{
      Node *tmp;
       int c = 0;
 
       //Traverse the entire Linked List
       for (tmp = p; tmp != NULL; tmp = tmp->link)
            c++;
 
       return (c);
}


int freeRam()
{
  extern int __heap_start, *__brkval;
  int v;
  return(int) & v - ( __brkval == 0 ? (int) & __heap_start : (int) __brkval);
}

void printFreeRam()
{
  Serial.print("Free RAM: ");
  Serial.println(freeRam());
}
 

void setup() {                
  Serial.begin(9600);
  printFreeRam();
  LinkList* pobj = new LinkList();
  printFreeRam();
  pobj->Append(11);
  printFreeRam();
  pobj->Append(22);
  printFreeRam();
  pobj->Append(33);
  printFreeRam();
  pobj->Delete(33);
  printFreeRam();
  pobj->AddatBeg(44);
  printFreeRam();
  pobj->AddAfter(1, 55);
  printFreeRam();
  pobj->Print();
  Serial.print("Number of elements in linked list: ");
  Serial.println(pobj->Count());
  delete pobj;
  printFreeRam();
}

void loop() {
}

Auch wenn im Node als "data" nur ein einfacher Integerwert steht, das RAM-Speichermanagement ist schon mal einwandfrei.

Und zwar wenn bei aktiver Liste mit "Append" ein Node an die Liste gehängt wird, der danach gleich wieder mit "Delete" entfernt wird. Aber auch wenn die Listeninstanz freigegeben wird, wird wieder derselbe Speicher als frei hergestellt, der vor dem Erzeugen der Listeninstanz frei war.

Vielleicht möchtest Du Dir ja diese Klasse dann einfach nur so erweitern, dass die Nodes dann de von Dir gewünschten Daten verwalten können und nicht nur diesen einen "data" Integerwert, der wohl auch als Schlüsselwert verwendet wird, um per "AddAfter" Einfügeoperationen nach einem bestimmten Listenelement zu ermöglichen, oder ein "Delete" mit Angabe des Schlüsselwerts zur Identifizierung des Eintrags, der gelöscht werden soll.

Die Klasse in dem Demoprogramm scheint mir recht einfach erweiterungsfähig zu sein.

P.S.: Von der Verwendung des Datentyps "String" ("String-Objekt") in Arduino-Sketchen kann ich nur komplett abraten, das ist völliger Unsinn und verbrät nur unnötig viel RAM-Speicher und Rechentakte für eine extrem wenig leistungsfähige Stringverarbeitung. Die leistungsfähigen Strings (C-Strings) auf Mikrocontrollern sind char-Arrays und char-Pointer!

@jurs: das die Funktion nicht korretk anzeigt, wusste ich zwar nicht :blush: aber leider korrespondiert sie mit der Praxis: wenn ich die liste lösche und wieder lade, können nur mehr ein,zwei sensore geladen werden, danach hängt der code wegen speichermangel.

Ursprünglich hatte ich ja nur char Arrays genutzt, aber da ich damit Probleme bei der Ausgabe/Eingabe via http und seriell hatte, hatte ich damals die strings eingeführt.

Danke für die LinkedList Klasse, da kann ich sicher das eine oder andere übernehmen, auch wenn ich versuchen möchte, die Klasse nicht zwingen einflechten zu müssen. :wink:

Aber kann es vielleicht daran liegen, dass ich eine Struktur benutze??
Warum sind Strings eigentlich so "böse"?

Aber kann es vielleicht daran liegen, dass ich eine Struktur benutze??

Eigentlich nicht. In C++ ist der einzige große Unterschied zwischen einem struct und einer Klasse, dass die Member eines structs standardmäßig public sind und die einer Klasse private

Warum sind Strings eigentlich so "böse"?

Die String Klasse verwendet dynamischen Speicher und macht dir Schweizer Käse aus deinem RAM wenn man sie nicht korrekt verwendet. Wenn du z.B. Strings mit + aneinander hängst wird jedesmal ein neues Objekt erzeugt und die alten zerstört.

Außerdem frisst sie generell viel mehr Ressourcen als char Arrays, ist langsam (durch den dynamischen Speicher und die Konstrukor und Destruktor Aufrufe) und zu nichts kompatibel. Die Funktionen die implementiert sind, sind minimal (wenn du dir im Vergleich mal die avr libc anschaust. Und hier für die Konvertierungs-Funktionen). Aber alle normalen Funktionen verlangen char Arrays. Also kann man keine Strings übergeben. Dann kann man sich nicht mal wie bei der C++ String Klasse mit c_str() einen Zeiger auf das interne Array geben lassen. Also einfach nur Schrott.

Hier ein wenig mehr dazu:
http://forum.arduino.cc/index.php?topic=233883.0

Danke für all eure Mühen!
@Serinify: Danke für deine Erklärung.

Ich hab jetzt die Strings gegen char arrays ausgetauscht, doch es ist immer noch ein Fehler drin.
Die Speicherangaben sind jetzt schön, aber es bleibt immer noch an der selben Stelle hängen!
Schaut mal auf die Ausgabe:

freier Speicher zu beginn 1186
1. Durchlauf --------------------------------------------------------------
Initialize / Generate Sensorlist
in funktion add sensor ALARMANLAGE EIN(KeyA)
freier Speicher 1112
in funktion add sensor ALARMANLAGE AUS(KeyB)
freier Speicher 1063
in funktion add sensor NACHTMODUS (D-ON)
freier Speicher 1014
in funktion add sensor NACHTMODUS (D-OFF)
freier Speicher 965
in funktion add sensor TEST1
freier Speicher 916
in funktion add sensor TEST2
freier Speicher 867
in funktion add sensor TEST3
freier Speicher 818
in funktion add sensor TEST4
freier Speicher 769
empty list
freier Speicher 1186
2. Durchlauf --------------------------------------------------------------
Initialize / Generate Sensorlist
in funktion add sensor ALARMANLAGE EIN(KeyA)
freier Speicher 1161
in funktion add sensor ALARMANLAGE AUS(KeyB)
freier Speicher 1161
in funktion add sensor NACHTMODUS (D-ON)
freier Speicher 1161
in funktion add sensor NACHTMODUS (D-OFF)
freier Speicher 1161
in funktion add sensor TEST1
freier Speicher 1161
in funktion add sensor TEST2
freier Speicher 1161
in funktion add sensor TEST3
freier Speicher 1161
in funktion add sensor TEST4
freier Speicher 1161
empty list
freier Speicher 1186
3. Durchlauf --------------------------------------------------------------
Initialize / Generate Sensorlist
in funktion add sensor ALARMANLAGE EIN(KeyA)
freier Speicher 1161
in funktion add sensor ALARMANLAGE AUS(KeyB)
freier Speicher 1161
in funktion add sensor NACHTMODUS (D-ON)

Warum um alles in der Welt, bleibt er gerade beim 3 Durchlauf hängen??? Das kann aj nur ein Speicher Problem sein....grrrrr
Ich blick da nicht durch.
Im Anhang hab ich den Sketch eingefügt. Könntet ihr doch noch einmal einen Blick drauf werfen?
Ich würd so gern verstehen, was ich falsch mache.... BIITTTEEE

sketch_feb21b.ino (7.84 KB)

Moment mal...

Du legst die structs mit new und löscht sie mit free(). free() ist das Gegenstück zu malloc()! Bei new muss man eigentlich delete machen und delete[] für Arrays.

infantilo:
Ich blick da nicht durch.

Ich glaube, Du erzeugst die Liste nicht ganz korrekt. Probier's mal damit:

//---------------------------------------------------------------------------------------------
// add a new sensor to list
// ---------------------------------------------------------------------------------------------
void addSensor(unsigned long id, char name[32], byte level, byte action, unsigned int timedelay) {
  a_sensor* node;
  a_sensor* new_sensor=new a_sensor; // create new sensor node
  // add data to fresh created new_sensor    
  new_sensor->id = id;
  strcpy(new_sensor->name,name);
  new_sensor->level = level;
  new_sensor->lasttime = 0;
  new_sensor->hastriggered = false;
  new_sensor->action = action;
  new_sensor->timedelay = timedelay;
  new_sensor->nextsensor = NULL; // end of list;
  
  Serial.print("in funktion add sensor ");
  Serial.println(name);  
  if(root == NULL) // list is empty
  {
    root = new_sensor; // new_sensor becomes root
  } 
  else
  {
    node = root;
    // then search for the end of the list
    while (node->nextsensor != NULL) node = node->nextsensor; 
    node->nextsensor= new_sensor; // add new_sensor at the last node
  }  
  Serial.print("freier Speicher ");
  Serial.println(freeRam());
}

Und zum Löschen der Liste:

void emptylist()
{
  a_sensor* nextnode;
  a_sensor* node=root;
  while (node != NULL)
  {
    nextnode=node->nextsensor;
    delete node;
    node=nextnode;
  }
  root = NULL;
}

@jurs: 100000 DANK!! Ich wäre nie auf die Idee gekommen, dass der eigentlich Fehler beim erstellen der Liste passiert! Nie! Natürlich wars das! Ich hab den code der Alarmanlage jetzt dahingehend geändert, die Strings verbannt und erstelle jetzt die List so wie du gesagt hast... Das Speichern und Laden funktioniert jetzt im laufenden Betrieb problemlos (hab aus lauter Freude mindestens 100 Mal hintereinander geladen... XD)

Nochmals DANKE Leute! Es ist total nett von euch eure Zeit zu investieren um anderen zu helfen OHNE die obligaten "dummen" Sprüche, die man sonst so hört. Andere hätten sich darauf beschränkt, mir zu zeigen wie richtig lösche, aber das hätte mein Problem ja nicht gelöst! Also HUT AB VOR EUCH!