Frage zu char* in struct
-
Hallo, bin neu hier in diesem Forum. Habe hierhergefunden, da ich mein erstes C-Programm schreiben will und im Internet auf der Suche nach Infos war. Hab durch die Suchen-Funktion hier im Forum auch schon einige interessante Dinge gefunden, aber hier mal eine Designfrage:
Ich möchte eine globale config-Variable haben, die Programmeinstellungen aus einer Datei lädt. Das config-struct enthält auch mehrere Strings.
Natürlich könne ich den Strings eine feste Länge zuordnen (z.B. char str01[100]), aber ich hab dann immer das Gefühl, schlecht zu programmieren, da ich so evtl. zu lange Strings abschneiden muss. Wenn ich alle Strings in der struct als char* deklariere, muss ich denen also beim Einlesen der Informationen Speicher zuweisen. Das sieht natürlich nicht so toll aus, wenn ich z.B. 20 verschiedene Werte einlese und stets davor ein malloc aufrufen muss. Dann am Ende des Programms nochmals dasselbe Spielchen mit free.
Ist das okay, oder ist das schlechter Stil? Das ist wie gesagt mein erstes C-Programm und ich will da am besten gleich lernen, wie man es richtig macht.Und hier gleich noch ne Frage hinterher. Was passiert beim folgenden Scenario:
Ich habe zu Beginn des Programmes verschiedenen Variablen Speicher zugewiesen und plötzlich tritt ein unerwarteter Fehler auf und ich will/muss das Programm beenden. Wenn ich einfach exit(1) aufrufe, dann beendet sich das Programm doch sofort und es führt nie meine free-Aufrufe aus, oder? Es kommt dabei zu Speicher-leaks und wenn ich das zu oft mache, dann wird mir mein Speicher knapp? Oder kann da das Betriebssystem dagegenarbeiten? (in meinem Fall ist es z.Z. Linux)Danke schon mal im Voraus!
-
zum 2. Punkt:
genau, der untere Code wird nichtmehr ausgeführt.
Am besten währe wohl du vernichtest im Fehlerfall alles selbst. Unter windoof wird das OS dagegenhalten das der speicher knapp wird und selbst aufräumen, davon sollte man aber nicht ausgehen, da n ANSI C Progg ja auch auf Linux,OS2 und sonstigem zeugs laufen sollte und da könnte es uU Leaks produzieren.
-
THE_FreaK schrieb:
zum 2. Punkt:
genau, der untere Code wird nichtmehr ausgeführt.
Am besten währe wohl du vernichtest im Fehlerfall alles selbst. Unter windoof wird das OS dagegenhalten das der speicher knapp wird und selbst aufräumen, davon sollte man aber nicht ausgehen, da n ANSI C Progg ja auch auf Linux,OS2 und sonstigem zeugs laufen sollte und da könnte es uU Leaks produzieren.Unter fast allen heutigen Betriebssystemen gibt es den Begriff des Prozesse und es gibt eine virtuelle Speicherverwaltung, die dafür Sorge trägt, dass ein Prozess nach seinem Ableben keine Ressourcen mehr unter Beschlag nimmt. Man sollte es mehr unter dem Gedanken Verwendbarkeit in einer Bibliothek, Verwendbarkeit als Unterprogramm sehen. Da kann man nicht einfach mal exit(EXIT_FAILURE) aufrufen. Man sollte bei einem fehlgeschlagenen malloc, realloc, calloc den zuvor verwendeten Speicher wieder freigeben und den Fehler in irgend einer Form melden. Grundsätzlich stimmt es aber nicht, dass ein exit() zu Memory-Leak etc führt. Und wenn du auf embedded devices deine Software schreibst, dann musst du selber genug über dieses Gerät wissen, um herauszufinden, wie man solche Situationen angeht.
Gruß Tobias
-
Ich würde vorschlagen Exit-Handler mit atexit() einzurichten.
"man atexit" hilft weiter...
-
hi!
es gibt auch ne andre möglickeit:
du lädst die config datei einfach in eine verlinkte liste:
struct {
char *name;
char *wert;
liste next;
}next;dann die methoden
getWert(char *name, char *wert)
[sucht name und setzt dann wert]
setWert(char *name, char *wert)
[sucht name und ändert dann den wert in der liste, bzw. erstellt den wer neu wenn er noch nicht existiert]loadWerte(char *dateiname)
[läd die werte in die liste]
saveWerte(char *dateiname)
[speichert die werte (also die liste) in die datei]und da du alle werte in einer liste hast kannst du dann ohne probleme die ganze liste wieder freigeben falls das programm abschmiert...
vom prinzip her ist das find ich ganz gut, ist zwar nicht so schnell, aber die werte werden normalerweise bei einer configdatei nur einmal eingelesen und bei programmende wieder zurückgesetzt und gespeichert... solangs weniger als 10.000 werte sind sollts eigentlich noch recht flott gehn
gruss,
matthias
-
Die Liste ist eine dritte Möglichkeit, aber man sollte sich Gedanken über den Zeitverbrauch zur Laufzeit machen. Werden die Config Werte nur wenig gebraucht so ist dies eine gute Lösung, wird aber im Programmablauf sehr oft auf diese Werte zugegriffen zahlt man doch eine sehr hohe Zeitstrafe durch die Liste.
Zu deinen beiden Möglichkeiten die Strings statisch oder dynamisch anzulegen.
Beide Methoden machen Sinn. Ist dir die Maximallänge bekannt so kann man diese konfig Werte statisch anlegen, hat den Vorteil das man sich keine Gedanken um malloc und free machen muss, speziell im Falle eines fatalen Fehlers. Der Nachteil ist der unnötig belegte Speicherplatz
Ist die Länge der Strings nicht vorhersehbar oder die Anzahl der Strings sehr hoch so bietet sich das dynamische Verfahren an. Nachteil im fatalen Fehlerfall die allocs wieder zu freen, Vorteil minimaler Speicherverbrauch.
Man kann hier keine dogmatische Lösung angeben immer so oder so. Vielmehr muss man sich beim Projektbeginn genau diese Fragen stellen und dann für dieses Projekt die richtige Lösung wählen, dies kann auch mal die Lösung mit der Liste sein, speziell dann wenn man dem Kunden vielleicht die Möglichkeit geben will selber noch Daten zur Konfiguration hinzuzufügen.
Bei den von mir bearbeiten Projekten war die Anzahl der Konfig Parameter meist nicht so groß, deshalb habe ich aus Bequemlichkeit mesistens die statische Lösung gewählt, dabei waren aber unter den Konfig Parameteren auch des öfteren Filenamen mit deren Hilfe ich dann weitere Daten in entsprchende Strukturen und Listen eingetragen habe.