Speicherfragen zu Arrays
-
Hallo Forumsbesucher,
ich bin einer Merkwürdigkeit auf der Spur, die ich leider nicht sinnvoll debuggen kann. Mein Progrämmchen sichert Variablen in externen Speicher, was auch eigentlich funktioniert, nur mit ganzen Arrays geht was schief:
struct data { unsigned int member0; unsigned int member1; unsigned int member2; char member3; }; const char elements = 25; // Prototyp multi_write(int adress, void *source, int size)); // *********************** int main(void) { struct data array[elements]; const int array_adress = 0x0e00; // irgendwas ins struct- array einfüllen multi_write(array_adress, &array[0], sizeof(array[0])*elements)); // und wegspeichern multi_write(array_adress, array, sizeof(array[0])* elements)); // und wegspeichern }
Problem: Er macht immer wieder mal das erste Array- Element kaputt, d.h., beim Rücklesen kommen falsche Werte.
- Erste Seltsamkeit, &array[0] und array sollten doch äquivalent sein, aber der Compiler generiert unterschiedlichen Assemblercode, der Fehler tritt bei beiden Varianten gleich auf - hat da jemand eine Ahnung, woran das liegen könnte?
- Zweite Frage ist, ob ich wirklich mit sizeof( ... die echte Größe des Arrays bekomme?
- In multi_write() wird der void* zu char* gecastet und dann char- weise von source bis source+size einzeln in den externen Speicher geschrieben. Die Frage dazu lautet, daß man zwar annehmen darf, daß es für das Programm so aussieht, als hätte man den Speicher en bloc, es aber nicht so sein muß. Bleibt das auch nach dem Pointercast so? Müßte doch eigentlich, oder?
Tut mir leid, daß ich so blöd fragen muß, aber ich bin in der Sache so weit, meine Grundkenntnisse in Zweifel zu ziehen ...
Danke für's Anschauen!
-
Der Kod'e von der funktion multi_write senden!
Um es zu verstehen.
-
liegt wohl daran, das der compiler füllbytes in deine struktur einfügt.
wegen dem alginment, der ausrichtung im hauptspeicher.#pragma pack(1) struct data { unsigned int member0; unsigned int member1; unsigned int member2; char member3; }; #pragma pack() // default Alignment
wenn du deine struktur so deklarierst, könnte sich das problem in wohlgefallen auflösen.
manche ziehen es auch vor, anstatt der pragma anweisung dummy bytes einzufügen, um auf gerade werte zwecks ausrichtung zu kommen:
struct data { unsigned int member0; unsigned int member1; unsigned int member2; char member3; char dummy_bytes[3]; };
struct data array[25]; printf("%d\n", sizeof( struct data)); // größe einer struktur printf("%d\n", sizeof( array));// größe 25* sizeof(struct data)
-
agga ugga schrieb:
liegt wohl daran, das der compiler füllbytes in deine struktur einfügt.
#pragma pack() mag der compiler nicht, ich kann das Alignment nur fileweise ändern, hab' mal das ganze force- even Zeugs und align- Dingsbums abgeschaltet. Die Data- section wird dadurch tatsächlich ein bißchen kompakter, das Problem bleibt aber bestehen ...
agga ugga schrieb:
manche ziehen es auch vor, anstatt der pragma anweisung dummy bytes einzufügen, um auf gerade werte zwecks ausrichtung zu kommen:
Ja, beim 16- Bitter wäre das das volle Byte, war's in dem Fall auch nicht. Auffüllen auf 32 Bit hat's auch nicht behoben ...
agga ugga schrieb:
struct data array[25]; printf("%d\n", sizeof( array));// größe 25* sizeof(struct data)
Siehst Du, da war ich mir nicht sicher, ob ich das so machen darf. Andersrum gefragt: Falsch war der vorherige Code aber auch nicht?
EDIT: Auf jeden Fall war er vorher so, daß es der Compiler mag - so jedenfalls nicht.Ramsis schrieb:
Der Kod'e von der funktion multi_write senden!
Das write- Dings ist eine alte Sünde von mir, hat aber bisher immer prima gefunzt. Ich müßte es ziemlich entrümpeln, um den Kern freizulegen und wollte vorher einfach sicher sein, daß der Bug nicht schon darüber liegt. Nimm's erstmal als Schonung des Forums hin
-
pointercrash() schrieb:
Andersrum gefragt: Falsch war der vorherige Code aber auch nicht?
das sollte auch so gehen.
-
agga ugga schrieb:
liegt wohl daran, das der compiler füllbytes in deine struktur einfügt.
wegen dem alginment, der ausrichtung im hauptspeicher.das wirds kaum sein, denn die füllbytes werden ja mitgezählt, wenn man sizeof() verwendet. ich glaube eher, die 'multi_write' funktion ist buggy.
-
sizeof-freak schrieb:
das wirds kaum sein, denn die füllbytes werden ja mitgezählt, wenn man sizeof() verwendet. ich glaube eher, die 'multi_write' funktion ist buggy.
Gut, dem Verdacht rutsche ich auch näher, aber es ist halt so, daß da hardwarenahes Zeug drinsteckt und ich gerade keine Hardware hier habe. Also ersuche ich Absolution von euch für den restlichen Kram zu erhalten
Auf meine Ausgangsfragen zurückgehend und erweitert, ich habe die sizeof- Sache im Verdacht, wer meinen vorigen Edit verpaßt hat:sizeof(array)
mag mein Compiler nicht. Ich glaube, ich sollte mal bei sizeof nachlesen ...
-
struct data d[25]; printf("%d %d %d\n", sizeof(struct data)*25, sizeof(d),sizeof(d[0])*25 );
das sind alles gleiche werte, die schreibweisen sind gleichwertig.
-
agga ugga schrieb:
das sind alles gleiche werte, die schreibweisen sind gleichwertig.
Du hast recht, ich Unrecht, ich hatte vorhin eine Klammer verschludert, sorry
Ich werde mir wohl den multi_write nochmal anschauen müssen, *seufz*.
Was mich in dem Zug erstaunt, was sizeof() für ein Tausendsassa ist. Dem ist es wurscht, ob er mit einem Typen, einem Arrayanker oder einem Arrayelement gefüttert wird. Kann mir jemand andeuten, wie das funktioniert oder einen guten Link dazu geben?
-
pointercrash() schrieb:
Kann mir jemand andeuten, wie das funktioniert oder einen guten Link dazu geben?
so lange der compiler die grösse eines objekts oder typs kennt, kann er überall wo du 'sizeof(..)' hinschreibst diesen wert einsetzten. sizeof ist keine funktion, sondern eher sowas wie ein platzhalter für die grösse von irgendwas und wird beim compilieren, also nicht zur laufzeit, ausgewertet.
-
sizeof(freak)==0
-
sizeof()-freak schrieb:
so lange der compiler die grösse eines objekts oder typs kennt, kann er überall wo du 'sizeof(..)' hinschreibst diesen wert einsetzten. sizeof ist keine funktion, ...
Gut, jetzt bitte nicht lachen: "array" war ja in dem Fall nur die Adresse auf das Array, woher weiß sizeof(), daß ich nicht die Größe haben will, die die Adresse einnimmt, sondern das Array, das sie referenziert.
Weiters: Wie bekäme ich denn die Adressgröße heraus?
-
pointercrash() schrieb:
"array" war ja in dem Fall nur die Adresse auf das Array, woher weiß sizeof(), daß ich nicht die Größe haben will, die die Adresse einnimmt, sondern das Array, das sie referenziert.
welche adresse? gibst du 'sizeof' ein array, dann kriegste die grösse des ganzen arrays. der compiler weiss, wie gross das array ist und diese information kannst du ihm mit 'sizeof' entlocken. die grösse eines elements bekommst du mit: sizeof (array[0]) oder *sizeof(array).
pointercrash() schrieb:
Weiters: Wie bekäme ich denn die Adressgröße heraus?
allgemein? etwa so: sizeof(void)*
-
adressen-freak schrieb:
allgemein? etwa so: sizeof(void)*
Ich denke pointercrash meint eher sowas:
sizeof &array[0]
-
Tim schrieb:
adressen-freak schrieb:
allgemein? etwa so: sizeof(void)*
Ich denke pointercrash meint eher sowas:
sizeof &array[0]
hast recht, das meinte er wohl.
überigens, du schreibst 'sizeof' ohne klammern, sowas sieht man selten.
wie ist es eigentlich mit sizeof a+b;?
ist das gleichbedeutend mit sizeof(a)+b oder ist es eher sizeof(a+b)?
-
klammern-freak schrieb:
überigens, du schreibst 'sizeof' ohne klammern, sowas sieht man selten.
Echt? Ich finde nicht. Wobei ich zugebe, dass ich es auch oft mit Klammern verwende. Manchmal braucht man sie ja auch:
sizeof(int)
geht ja nicht ohne.klammern-freak schrieb:
wie ist es eigentlich mit sizeof a+b;?
ist das gleichbedeutend mit sizeof(a)+b oder ist es eher sizeof(a+b)?
Ersteres. Auch ein gutes Beispiel wo es mit Klammern besser wäre
-
Tim schrieb:
Ich denke pointercrash meint eher sowas:
sizeof &array[0]
Meinte er
Das sizeof(void ) ist insofern problematisch, weil mein Compiler ein near/far- Modell hat und ich ihn zwingen kann, bestimmte Sachen im near- Bereich anzulegen. Bei void geht er automatisch von far aus.
Sindsize_t s= sizeof(&array[0]); size_t s = sizeof(&array);
dann wirklich äquivalent?
Übrigens bin ich bei der multi_write()- Methode wirklich auf was gestoßen, im Original belegt die struct 28 Bytes und es gibt 10 Elemente im Array, die Blocksize der adressierten Speicher ist aber maximal 256 Byte groß - na, schnackelt's
. Typisch Modulo- Rollover.
Ist mir nur nie aufgefallen, weil ich anscheinend nie mehr als 255 Bytes am Stück geschrieben habe, werd' das Ding zunächst zurechtfrickeln und irgendwann demnächst neu aufsetzen.Aber schön, wieder mal an den Basics genagt zu haben
-
pointercrash() schrieb:
Sind
size_t s= sizeof(&array[0]); size_t s = sizeof(&array);
dann wirklich äquivalent?
Nicht so richtig. Es sind untetschiedliche Typen. Ersteres ist
T*
, letzteres einT(*)[NUM]
. Wobei ich mir jetzt gerade keinen Fall vorstellen kann, wo das Ergebnis von sizeof unterschiedlich wäre
-
Tim schrieb:
Wobei ich mir jetzt gerade keinen Fall vorstellen kann, wo das Ergebnis von sizeof unterschiedlich wäre.
es gibt keinen. beides ist die adresse des ersten elements des selben arrays. selbst mit near/far kann man keinen unterschied erzwingen (es sei denn, der compiler ist kaputt).
-
Tim schrieb:
Nicht so richtig. Es sind untetschiedliche Typen. Ersteres ist T*, letzteres ein T(*)[NUM].
gut erklärt
So findet man es nicht in einem Buch.