Speicheranlage für Arrays



  • Werteste ANSI- Paper- Experten,

    das müßtet Ihr doch aus dem EffEff wissen: 😃
    Kann man sich bei einem Array darauf verlassen, daß die Elemente tatsächlich sequentiell im Speicher liegen ? 😕
    Um Variablen stromausfallgesichert in einem EEPROM abzulegen, mache ich Folgendes:

    char DriveXSaveVars(void)
    {
    	if (I2cEeMultiWrite(alltubes_adress, &alltubes[0], sizeof(alltubes[0]) * elements);	// adress (0.. 32767), Varpointer, Bytezahl
    		return 255;
    	else 
    		return 0;
    }
    

    Die aufgerufene Funktion übernimmt die Referenz &alltubes[0] als void*, interpretiert sie als char* und liest die chars sequentiell bis zur übergebenen Bytezahl. Das Auslesen funktioniert im Prinzip genauso.
    Mit trivialen Typen wie int, float, etc. funzt das auch prima, momentan kriege ich aber nur Datensalat aus dem Baustein zurück, wenn ich ein Array mit struct- Elementen übergebe.
    Wahrscheinlich habe ich den Bock woanders geschossen 🙄 , wollte aber diese Fehlerquelle im Vorfeld ausschließen.

    Um es in klare Fragen zu gießen: Darf man gesichert annehmen, daß die Elemente eines Arrays ohne Lücken sequentiell im Speicher angelegt werden? Auch, wenn die Elemente komplexer sind?
    Als Erweiterung dessen: Gilt das auch für auf dem Heap angelegte dynamische Bereiche?

    Danke für die Antwort im Voraus! 😉



  • pointercrash() schrieb:

    Um es in klare Fragen zu gießen: Darf man gesichert annehmen, daß die Elemente eines Arrays ohne Lücken sequentiell im Speicher angelegt werden? Auch, wenn die Elemente komplexer sind?

    Dass sie sequentiell im Speicher liegen ist garantiert, sonst würde ja z.B. Zeigerarithmetik auf Arrays nicht funktionieren. Nicht garantiert dagegen ist, dass es keine Padding Bytes zwischen/in den einzelnen Elementen gibt.



  • pointercrash() schrieb:

    Um es in klare Fragen zu gießen: Darf man gesichert annehmen, daß die Elemente eines Arrays ohne Lücken sequentiell im Speicher angelegt werden? Auch, wenn die Elemente komplexer sind?
    Als Erweiterung dessen: Gilt das auch für auf dem Heap angelegte dynamische Bereiche?

    Beides mit "ja" zu beantworten.
    Sowohl mit malloc() als auch mit realloc().

    http://www.opengroup.org/onlinepubs/009695399/functions/malloc.html
    http://www.opengroup.org/onlinepubs/009695399/functions/realloc.html

    Ganze entscheidende Sätze sind aber:

    The malloc() function shall allocate unused space for an object whose size in bytes is specified by size and whose value is unspecified.

    realloc:
    If the new size is larger, the contents of the newly allocated portion of the object are unspecified.

    Danach hört es sich zumindest bei dir ein bischen an 😉

    Btw um Paddingsbytes zu "vereinheitlichen" initialisiere deine Struct am Anfang mit "0", z.b. beim Vergleich von 2 Structs...

    mystruct *test;
    test=malloc(sizeof(mystruct));
    memset(test,0,sizeof(test));
    

    Und noch ne kleine "dirty" Ergänzung:
    Durch Preprocessor Anweisungen kannst du dem Compiler dieses Alignment (Padding Bytes) "verbieten". Nachteil - die Performance wird schlechter... ist aber kein Standard mehr. 😮

    Greetz



  • ...hat zwar nichts mit der frage zu tun, aber in dem länglichen funktionsaufruf ist ganz hinten ein semikolon zu viel.
    🙂



  • Danke an alle für die Antworten!

    pale dog schrieb:

    ...hat zwar nichts mit der frage zu tun, aber in dem länglichen funktionsaufruf ist ganz hinten ein semikolon zu viel.
    🙂

    Stimmt, pure Schlamperei, ich hatte es aus meinem "Testing"- Part ohne compilieren c&p ... soll man nich', ich weiß 🙄

    codefrag schrieb:

    ...realloc:
    If the new size is larger, the contents of the newly allocated portion of the object are unspecified.

    Danach hört es sich zumindest bei dir ein bischen an

    War's in dem Fall nicht (da fixe Größe), hat aber zu interessanten Experimenten und zur Aufdeckung eines ganz anderen Fehlers geführt. Wenn ich realloziere und hinter dem ursprünglichen Datenblock war noch was anderes alloziert, zieht der Datenblock komplett um, was je nach Datenmenge ziemlich dauern kann. Hat an einer anderen Codebaustelle zu Timeoutfehlern geführt. En passant einen anderen Fehler zu erwischen, danke! 😃

    codefrag schrieb:

    Btw um Paddingsbytes zu "vereinheitlichen" initialisiere deine Struct am Anfang mit "0", z.b. beim Vergleich von 2 Structs...

    Mhmm, ich hätte da "calloc()", ist doch auch Standard, oder 😕 Dann kriege ich das doch in einem Aufwasch?

    codefrag schrieb:

    Und noch ne kleine "dirty" Ergänzung:
    Durch Preprocessor Anweisungen kannst du dem Compiler dieses Alignment (Padding Bytes) "verbieten". Nachteil - die Performance wird schlechter... ist aber kein Standard mehr.

    Gut, bei mir sind's Compiler- Switches, die das Alignment beeinflussen und ich gewänne 3 Byte pro Element. Lasse ich das Alignemt auf optimal, fallen Stopf- Bytes an, aber die setzt er alle explizit auf "0". Denke, daß es da doch so ist, daß an irgendeiner Stelle gewährleistet sein muß, daß Elemente vergleichbar bleiben und "0" mitzuschreiben ist das, was keine Rechenzeit kostet, eben weil der Zugriff aligned erfolgt.

    Achja:
    Bei mir war's letztendlich ein falsch abgefangener Adress- Rollover bit5->bit6, der bisher nie zum Tragen kam ... nicht lachen, den Bug habe ich seit drei Jahren in meiner Library und selbige folglich zuallerletzt verdächtigt. 😞
    Jedenfalls geht's jetzt auch mit großen Arrays von Structs 🙂

    ThanX!



  • pointercrash() schrieb:

    codefrag schrieb:

    Btw um Paddingsbytes zu "vereinheitlichen" initialisiere deine Struct am Anfang mit "0", z.b. beim Vergleich von 2 Structs...

    Mhmm, ich hätte da "calloc()", ist doch auch Standard, oder 😕 Dann kriege ich das doch in einem Aufwasch?

    calloc() ist Standard und sollte äquivalent zur Kombination malloc/memset sein. Leider gibts kein crealloc() 😉


Anmelden zum Antworten