Also ich bastle gerade mit Strukturen rum und bin mir ziemlich sicher,
dass ich hier Fehler mache. Daher wäre für mich und evtl andere
interessant was man hierbei beachten soll.
Die Größe eines "normal" angelegten Structs kann man ja anscheinend mit
1
i=sizeof(struct_Benutzer);
bestimmen.
Falls ich aber folgendes mache, mache ich dann etwas falsch?
1. Frage: Nein, sizeof kann auf jeden beliebigen Datentyp angewandt
werden.
2. Frage: Ja, und wenn struct_Benutzer ein Zeiger auf die Struktur
ist, kannst du ihn anschließend ähnlich einem Arryay mit 10 Elementen
des Typs struct_def_Benutzer verwenden. So legt man dynamische Arrays
an.
Achso. Na gut. Ich benutze gerade in meinem Programm solche Arrays etc.
aber anscheined mache ich etwas grundlegendes falsch. Mein µC stirbt
leider immer, wenn ich mein Array anlege. Irgendetwas muss mit der Größe
nicht stimmen. Hmm. Ich forsche weiter und schreibe sicher bald wieder
was hier rein. :)
Das typedef hat da nichts verloren. Wenn Du den Strukturtyp weiterhin
als "struct BLABLA" ansprechen willst, hat das typedef keinerlei
Funktion.
Wenn typedef, dann so:
>
die richtige Größe an Malloc() übergebe, aber ein
sizeof(struct_Benutzer) nur '2' zurück liefert. Das wird wohl der Fehler
sein, da ich danach wohl richtig übel einen Überlauf produziere. Aber
warum stimmt die Größe nicht?
> Mir ist gerade aufgefallen, dass ich zwar mit>> struct_Benutzer = malloc(10 * sizeof(struct_def_Benutzer));>> die richtige Größe an Malloc() übergebe
So und nicht anders wird das gemacht.
> (...) aber ein sizeof(struct_Benutzer) nur '2' zurück> liefert. Das wird wohl der Fehler sein, da ich danach> wohl richtig übel einen Überlauf produziere. Aber> warum stimmt die Größe nicht?
Die Größe stimmt. Nur willst Du ja nicht Speicher für zehn Pointer auf
eine Struktur anfordern, sondern Speicher für zehn Strukturen.
Also musst Du es so machen, wie eingangs bereits erwähnt.
Du solltest übrigens deutlicher voneinander zu unterscheidende
Typnamen und Variablennamen verwenden; daß Deine Struktur fast
genauso heißt wie die Pointervariable ist nicht hilfreich.
Ich hab mal ein paar Test mit anderen Funktionnen gemacht. Wenn ich
später in einer anderen Funktion mittels struct_Benutzer[0].Name oder
ähnlich auf meinen reservierten Speicher zugreifen, bekomme ich bei
jedem Aufruf der Funktion einen anderen Wert. Es schaut also stark
danach aus, dass mir der Speicher nicht reserviert wurde. Wenn ich
jedoch unmittelbar nach dem Anlegen darauf zugreife, dann steht alles
wunderbar drin.
Man man. Ich würde ja meinen ganzen Code mal posten, aber der ist voll
mit anderen Sachen und eigentlich auch ganz anders. Das mit
struct_Benutzer war nur eine Vereinfachung für den Thread hier.
Josef wrote:
> Es schaut also stark> danach aus, dass mir der Speicher nicht reserviert wurde.
Nein, es sieht danach aus, dass ihn jemand danach überschrieben hat.
"Reservieren" kannst du ihn nur für weitere malloc(), du kannst aber
keinen Speicherplatz beim Prozessor "reservieren", auf den der dann
nicht mehr schreiben kann...
Wie andere dir schon geschrieben haben, du hast einen ziemlichen
Wirrwar in deinen Bezeichnungen, der es dir (und auch anderen ;-)
mental einfach nicht mehr erlaubt, den Überblick zu behalten. Solange
du Typnamen vergibst, die zwar einen Zeiger definieren (dessen sizeof
bei deinem Controller offensichtlich 2 ist), die aber so heißen, als
würden sie eine ganze Struktur beinhalten, ist es kein Wunder, dass
da hinterher Speicher überschrieben worden ist, der gar nicht alloziert
worden war.
Wenn du eine Struktur allozieren willst, dann mach dir von mir aus
einen Datentyp für diese Struktur, aber alloziere dann auch die
ganze Struktur. (Das Ergebnis der Allokation ist dann ein Zeiger
auf die Struktur.) Wenn du 10 davon allozieren willst, dann
multipliziere das mit 10.
sizeof von einem Zeigertyp zu bilden hat in diesem Zusammenhang keinen
Sinn, sondern deutet nur darauf hin, dass du gar nicht verstanden
hast, was du da gerade tust.
Auf den Inhalt eines Structs, der in einem per malloc erzeugten
Speicherbereich liegt, kann man eigentlich nie mit
1
struct_Benutzer[0].Name
zugreifen. Da wird immer ein Pointer mit im Spiel sein.
Mit "ungefähr so" oder "so ähnlich wie" wird das nie was.
Nur so aus Interesse: Für welches Zielsystem programmierst du
eigentlich?
Oliver
> Auf den Inhalt eines Structs, der in einem per malloc erzeugten> Speicherbereich liegt, kann man eigentlich nie mit>> struct_Benutzer[0].Name>> zugreifen. Da wird immer ein Pointer mit im Spiel sein.
O doch, das geht ganz genau so. Das ist der Array-Pointer-Dualismus.
Vorausgesetzt, die "sinnvoll" benannte Variable struct_Benutzer wird so
genutzt:
Auf den Inhalt eines Structs, der in einem per malloc erzeugten
2
Speicherbereich liegt, kann man eigentlich nie mit
3
4
struct_Benutzer[0].Name
5
6
zugreifen. Da wird immer ein Pointer mit im Spiel sein.
Warum nicht. Das mache ich schon immer so. :) Dachte das sei auch ok so.
Wie greife ich dann komfortabel darauf zu?
Leider muß ich hier malloc() benutzen weil ich die Größe des "Arrays"
zur Compilerzeit nicht kenne.
PS: Was passiert eigentlich mit lokalen Arrays, dessen Größe auch zur
Compilerzeit nicht existieren? Ich reserviere in der Funktion nämlich
einen Buffer nammens acbuff[Filelength()]. Wobei Filelenght eben erst
bekannt ist, wenn das Programm läuft und auf eine SD-Karte zugreifen
kann.
PPS: Ich nutze einen AT90CAN128
@Jörg
Du hast schon recht, dass ich nicht recht weiß was ich tue. Ich versuche
eben mit dem was ich weiß zu arbeiten. Das ich nicht wußte das sizeof()
mit dem Pointer nicht zurückgibt was ich mir wünschte, war eben blöd
angestellt.
Trotzdem finde ich es schon ein bißchen abwertend was da geschrieben
wurde.
Also ich weiß echt nicht mehr weiter.
Nachdem ich in meiner Funktion mit malloc mein Array abgespeichert habe
und diese Funktion (ohne free) wieder verlassen habe, existieren meine
Werte noch "kurz".
Ich gehe jetzt davon aus, dass mir dieser Speicherbereich "gehört". Und
da ich ja meine Pointervariable als extern angelegt habe, sollte diese
doch auch noch existieren.
Wenn ich aber später die Adresse in meinem Pointer anschaue, dann ist
das garnicht mehr die, die mir malloc() in meiner Unterfunktion
übergeben hat.
Warum?
> Wenn ich aber später die Adresse in meinem Pointer anschaue, dann ist> das garnicht mehr die, die mir malloc() in meiner Unterfunktion> übergeben hat.>> Warum?
Weil irgendwas den Pointer überschreibt?
Wie und wo ist denn der Pointer deklariert?
Wie wäre es mit Sourcecode?
OK. Hier mal mein Programm mit all seiner Unschönheit :)
Ich weiß das ist nicht so geschrieben, dass es schnell für jeden
nachvollziebar ist, aber soll ja auch für mich sein. ;)
hab versehentlich das richtige mal auskommentiert um was zu testen.
Leider hab ichs nie wieder rückgängig gemacht :(
Jetzt hab ich festegestellt, dass alles läuft bis auf die Pasage mit
strncmp.
Das die Adresse stand einen Wert zu hoch, also das "+1" weg und schon
war die Tabelle gut. Leider passiert hier etwas böses:
Hmm.
Wenn inbuff als Array der Länge 10 definiert ist, dann
kann doch der Text DATA_ATTR_NULL gar nicht drinn stehen,
denn das sind ja schon 14 Zeichen (ohne abschliessendes '\0').
Also entweder ist der Text falsch, oder (was wahrscheinlicher ist),
die Arraygröße mit 10 ist viel zu klein.
Ja. Tut mir leid. Wie oben beschrieben habe ich das mal fälschlich zu
testzwecken definiert. das muss ein Array der Größe Filelength() sein,
damit ist dann die ganze Datei in dem Array.
Aber leider funktioniert strncmp und memcmp nicht. Dort stirbt mein
Programm. Das es kein echter String ist, weiß ich aber da ich ja
sowieso nur eine bestimmte Anzahl von Zeichen prüfe, sollte die
Nullterminierung egal sein, oder?
PS: Wenn ich inbuff[Filelength] definiere, laufe ich dann hier auch
Gefahr der Speicherfragmentierung?
> PS: Wenn ich inbuff[Filelength()] definiere, laufe ich dann hier auch> Gefahr der Speicherfragmentierung?
Nein, das ist eine automatische Variable, und die wird auf dem Stack
angelegt.
Josef wrote:
> Aber Filelength() (Größe der Datei auf der SD Karte) liefert ja erst zur> Laufzeit einen Wert... Woher weiß der Compiler dann wie groß die sein> muß?
Gar nicht.
Seit einiger Zeit geht das in C. Man kann Arrays dynamisch zur
Laufzeit in der Größe festlegen.
Wie der Compiler das genau realisiert, kann ich nicht sagen.
Er könnte es durch eine Stackpointer Manipulation zwischendurch
machen, oder er könnte auch auf malloc() ausweichen. Wenn ich
raten müsste, dann würde ich auf letzteres tippen, weil diese
Stackallokierung bei mehreren dynamischen Arrays sonst in ein
Problem ausarten könnte. Der Weg über malloc() ist dann doch
deutlich einfacher: Für das Array wird ein Pointer am Stack
angelegt, für die Allokierung wird ein malloc() gemacht und
in jedem Pfad der zum Verlassen des Arrays führt wird der
korrespondierende free() gemacht. Ist aber nur eine Vermutung.
Aber eines steht auf jeden Fall fest: Wenn nicht genug Speicher
für das Array vorhanden ist, dann gibts Probleme.
GCC hat diese Möglichkeit schon sehr lange gehabt in Form der Funktion
alloca(). Die gleiche Mimik wird (und wurde auch schon sehr lange,
ist aber mit C99 erst offiziell geworden) auch für dynamische Arrays
benutzt.