Fehlermeldung beim Beenden des Programms
-
Guten Tag,
Ich habe ein kleines Programm geschrieben, um das Thema Pointer, Pointer in Strukturen, Listen usw. besser zu verstehen. Das Programm läuft, doch wenn ich es mit Enter beenden will (getchar) erscheint eine von diesen wahnsinnig aussagekräftigen Windoof "Senden/Nicht senden" Fehlermeldung. Kann mir vielleicht jemand sagen wieso? Der Compiler bringt weder Fehler noch WarnungHier noch der Code(Ich weis, es sind ein wenig lange Kommentare, aber es soll wie gesagt dem Verständnis dienen
):
#include <stdio.h> #include <conio.h> #include <stdlib.h> #include <strings.h> int main(void) { /*Hier wird der Typ "t_Person" definiert*/ typedef struct person{ char name[20]; int alter; }t_person; /*------------------------------------------------------------------------*/ printf("Statisches Array"); printf("\n================\n\n"); /*Eine Variable(Array/statisch) vom Typ "t_person" wird deklariert*/ t_person statKlasse[17]; /*Zugriff und Ändern der Strukturvariablen. Wenn in einer Variable eine Eigenschaft vom Typ char-array verändert werden will, muss mit dem Befehl "strcpy" gearbeitet werden.(siehe unten)*/ strcpy(statKlasse[0].name,"Peter"); statKlasse[0].alter = 20; strcpy(statKlasse[17].name,"Sarah"); statKlasse[17].alter = 21; /*Ausgabe der veränderten Positionen der Variable "klasse"*/ printf("Name: %s", statKlasse[0].name); printf("\nAlter: %i", statKlasse[0].alter); printf("\n..."); printf("\nName: %s", statKlasse[17].name); printf("\nAlter: %i", statKlasse[17].alter); printf("\n\t\t!Zugriff ueber: Variable.Eigenschaft!"); /*Dies war das statische Array, dieses hat den Vorteil, dass es programmier- technisch weniger aufwendig ist als das dynamische. Jedoch wird damit viel Arbeitsspeicher bereits beim Start des Programmes "unnötig" reserviert.*/ /*------------------------------------------------------------------------*/ printf("\n\n================================================================================"); printf("\n\n(Halb-)Dynamisches Array"); printf("\n========================"); /*Eine Variable(Array/dynamisch,pointer) vom Typ "t_person" wird deklariert*/ t_person *dynKlasse[18]; /*Da wir im Moment kein richtiges Array haben, sondern nur Zeiger, muss für jedes Element "Platz"(Speicher) geschaffen werden. Dies wäre in diesem Fall soviel Speicher, wie es braucht um 1 Person(Name,Alter) abzuspeichern. Also konkret: Speicher für eine Variable vom Typ "t_person"*/ dynKlasse[0] = malloc(sizeof(t_person)); dynKlasse[17] = malloc(sizeof(t_person)); /*Ab hier können die Positionen im Array gleich wie beim statischen Array verändert werden, ABER der Zugriff erfolgt über den Pfeil(->), nicht über den Punkt(.)!!! (Man achte nochmals auf den Befehl "strcpy", der für die Zuweisung von Strings an ein char-array zuständig ist.)*/ strcpy(dynKlasse[0]->name, "Stefanie"); dynKlasse[0]->alter = 19; strcpy(dynKlasse[17]->name, "Markus"); dynKlasse[17]->alter = 22; /*Es werden wiederum die veränderten Positionen in der Konsole ausgegeben*/ printf("\nName: %s", dynKlasse[0]->name); printf("\nAlter: %i", dynKlasse[0]->alter); printf("\n...\n"); printf("\nName: %s", dynKlasse[17]->name); printf("\nAlter: %i", dynKlasse[17]->alter); printf("\n\t\t!Zugriff ueber: Variable->Eigenschaft!"); /*Wenn diese Werte nicht mehr benutzt werden kann der benutzte Speicher mit dem Befehl "free()" wieder freigegeben werden*/ printf("\n\n->Inhalt wird geloescht und der Speicher freigegeben..."); //free(dynKlasse[0]); //free(dynKlasse[17]); getchar(); return 0; /*Das oben gezeigte Beispiel zeigt eigentlich ein Halb-Dynamisches Array. Es ist nicht wirklich dynamisch, da man bei der Deklaration der Variablen(hier: dynKlasse[18]) die Anzahl der im Array gespeicherten Zeiger angeben muss(hier: 18). Man kann es also nicht beliebig erweitern. Bei einer Datenbank wäre das nicht brauchbar, da die Anzahl der Einträge begrenzt ist. Doch diese Lösung ist sicher besser als die statische, wenn es darauf ankommt Ressourcen zu sparen(Arbeitsspeicher).*/ }
Danke schon im Voraus für eure Hilfe!
mfg PapaNoah
-
Auffällig ist, dass du bei t_person statKlasse[17] ein Element zu wenig holst (den Fehler machst du weiter unten komischerweise nicht). Das zerschiesst dir wohl den Stack.
-
Tim schrieb:
Auffällig ist, dass du bei t_person statKlasse[17] ein Element zu wenig holst (den Fehler machst du weiter unten komischerweise nicht). Das zerschiesst dir wohl den Stack.
Vielen Dank, genau das war der Fehler!
Blöde Anfängerfehler
Schönen Tag noch
mfg PapaNoah
-
PapaNoah schrieb:
/*Das oben gezeigte Beispiel zeigt eigentlich ein Halb-Dynamisches Array. Es ist nicht wirklich dynamisch, da man bei der Deklaration der Variablen(hier: dynKlasse[18]) die Anzahl der im Array gespeicherten Zeiger angeben muss(hier: 18). Man kann es also nicht beliebig erweitern. Bei einer Datenbank wäre das nicht brauchbar, da die Anzahl der Einträge begrenzt ist. Doch diese Lösung ist sicher besser als die statische, wenn es darauf ankommt Ressourcen zu sparen(Arbeitsspeicher).*/ }
Der Arbeitsspeicher ist selten heute ein Problem (sonst waeren die ganzen C++-Klassen, die aus Performancegruenden Arbeitsspeicher "auf Vorrat" halten schon lange aus dem Rennen).
Das Problem liegt darin, dass malloc fast immer sehr viel schneller ist als realloc; also die Veraenderung der Groesse des Arrays Zeit kostest. Die klassische Loesung fuer solche Probleme ist und bleibt die verkettete Liste. Man spart sich auch den Aufwandt des Check-up gegen Boundary-Verletzungen.
-
hartmut1164 schrieb:
Das Problem liegt darin, dass malloc fast immer sehr viel schneller ist als realloc; also die Veraenderung der Groesse des Arrays Zeit kostest.
Behauptung ohne Beleg.
hartmut1164 schrieb:
Die klassische Loesung fuer solche Probleme ist und bleibt die verkettete Liste.
Ich denke das zu lösende Problem sollte die zu wählende Datenstruktur bestimmen. Dann natürlich noch andere Faktoren wie z.B. Caching, Speicherfragmentierung, ...
hartmut1164 schrieb:
Man spart sich auch den Aufwandt des Check-up gegen Boundary-Verletzungen.
Liste: p->next != NULL
Array: i < countWas da jetzt wo gespart wird ist mir noch nicht so ganz klar.
-
Tim schrieb:
hartmut1164 schrieb:
Das Problem liegt darin, dass malloc fast immer sehr viel schneller ist als realloc; also die Veraenderung der Groesse des Arrays Zeit kostest.
Behauptung ohne Beleg.
Ueberlege Dir mal was auf unterer Ebene beim malloc und realloc gemacht werden muss.
Beim malloc muss nur freier Speicher gesucht werden und reserviert. Bei realloc muss geschaut werden, ob "hinter" der letzten Position noch Platz ist, wenn ja, dann diesem reservieren, ansonsten die schon bestehenden Daten an eine andere Position copieren. Das ist erheblich mehr Aufwandt.
Tim schrieb:
hartmut1164 schrieb:
Die klassische Loesung fuer solche Probleme ist und bleibt die verkettete Liste.
Ich denke das zu lösende Problem sollte die zu wählende Datenstruktur bestimmen.
Richtig, aber wenn die Anzahl meiner Datensaetze flexible sein soll, dann ist eine verketete Liste immer eine gute Idee.
Tim schrieb:
Dann natürlich noch andere Faktoren wie z.B. Caching, Speicherfragmentierung, ...
Fragmentierter Arbeitsspeicher ist bei modernen Prozessoren und Betriebssystem kein Problem mehr - aber selbst hier waere die Liste ueberlegen, weil deren Elemente eben nicht in einer Sequenz im Speicher stehen muessen.
Caching ist sehr prozessorabhaenig und ich ziehe es vor, dies den Authoren der Libraries zu ueberlassen.
Tim schrieb:
hartmut1164 schrieb:
Man spart sich auch den Aufwandt des Check-up gegen Boundary-Verletzungen.
Liste: p->next != NULL
Array: i < countWas da jetzt wo gespart wird ist mir noch nicht so ganz klar.
Das Problem ist dabei, dass dieses count ueberall present sein muss, wo die Daten zugreifst. Es reicht eben nicht mehr aus einfach einen Pointer auf das erste Element zu uebergeben. Wenn Du nicht mit globalen Variablen arbeiten willst, musst dies ueberall explizied durchreichen. Das ist aber dann auch eine Sache des Stils.
-
hartmut1164 schrieb:
Beim malloc muss nur freier Speicher gesucht werden und reserviert. Bei realloc muss geschaut werden, ob "hinter" der letzten Position noch Platz ist, wenn ja, dann diesem reservieren, ansonsten die schon bestehenden Daten an eine andere Position copieren. Das ist erheblich mehr Aufwandt.
kommt drauf an. 'realloc' wird möglicherweise zu malloc, rüberkopieren des inhalts und 'free' des alten blocks. sowas ist dann richtig mies.