Schwierigkeit bei Speicheralloziierung //Erledigt kann geschlossen werden



  • Hallo,

    ich habe ein kleines Problem an dem ich jetzt schon eine weile Knoble und nach Loesungen suche.
    Ich finde allerding nicht heraus woran es liegen kann. In den ganzen HowTo's wird immer wieder die ein oder andere int-liste etc. behandelt aber nichts was mir weiter hilft.

    Bei folgendem Programmschnipsel schlaegt haut mir irgend was den Speicher kaputt oder malloc funktionert anders als von mir erwartet. (Was wohl wahrscheinlicher ist.)

    Bei diesem Programm treten keine Probleme auf, solang die variable length in (Zeile 45) Werte aus [1..38] hat. Alles darueber hinaus fuehrt zu einen Segmentation fault in Zeile 34. Malloc selber gibt errno=0 und auch keinen NULL-Pointer zurueck. Aber wie viel/wenig wurde da nun alloziiert? 😕
    Die Pointer sind jedenfalls richtig. Jedoch darf ich in row->length nichts schreiben. 😮

    Kann mich hier jemand erleuchten?
    Ich glaube ja das liegt an der Verwendung der Strukturen zusammen mit sizeof(); aber was schlaegt hier daneben und wie kann ich das umgehen?

    Arbeiten tue ich auf einer Sun unter Solaris.

    vielen Dank im Voraus!

    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    
    typedef struct{  
    	double value;  
    	int index, next;
    }  BCRSEntry;
    
    typedef struct { 
    	int length, count, first, free;
    } BCRSRow;
    
    #define mSizeOf_BCRSRow   ( (unsigned int) sizeof(BCRSRow)    )
    #define mSizeOf_BCRSEntry ( (unsigned int) sizeof(BCRSEntry)  )
    #define mBCRSEntryOffset(i)    ( mSizeOf_BCRSRow + ((unsigned int)(i)) * mSizeOf_BCRSEntry ) 
    #define mBCRSEntry(r,idx)      ( (BCRSEntry *)((r) +  mBCRSEntryOffset(idx)) )
    #define mBCRSRowSize(count)    ( (unsigned int) (  mSizeOf_BCRSRow + ( ((unsigned int)(count)) * mSizeOf_BCRSEntry )))
    
    int BCRSRowAlloc(BCRSRow **R, int cols){
      size_t length = 0;
      BCRSRow *row;
      if (cols < 1) {
        printf("ERROR: allocating row with no entries\n");
        return -1;
      }
      length = mBCRSRowSize(cols);
      row =  malloc( length );
      if ( row == NULL ) {
         printf("ERROR: allocation of vector failed!\n");
         return -1;
      } else {
         *R = row;
         row->length = cols;
         // do more stuff with row
      }
    }
    
    int main( char *argv, int *argc  ){
    	double value;
    	BCRSRow *v = NULL;
    
            printf("==================================\n");
    
            length = 37;  // <<<<<<<<<<<<<<<<<<<<<<  
    
            if (BCRSRowAlloc(&v,length) < 0) { 
                 printf("allocation failed");
                 return -1;
            }
            // do stuff
            free(v);
            v = NULL;	
    
            printf("done\n");
    	return 0;
    }
    


  • row =  malloc( length );
    

    fehlt da nicht was?? Müsste das nicht heißen:

    row =  malloc( sizeof(....)*length );
    

    oder täusche ich mich da?

    Gruß
    Sascha



  • könnte am padding liegen..... es kann sein,
    das der compiler zwischen bytes in den structuren anlegt zur optimierung.

    Prüf doch mal: was kommt hier raus?

    typedef struct { 
        int length, count, first, free;
    } BCRSRow;
    
    sizeof(BCRSRow)=?
    

    normalerweise 16



  • NMCM schrieb:

    Die Pointer sind jedenfalls richtig. Jedoch darf ich in row->col nichts schreiben. 😮

    Du hast in der struktur kein col feld definiert.

    NMCM schrieb:

    Aber wie viel/wenig wurde da nun alloziiert? 😕

    Speicherblock, der von malloc geliefert wird.

    row =
    ------------------------------------------------------
    | sizeof struct BCRSRow |
    ------------------------------------------------------
    | count * sizeof struct BCRSEntry |
    | |
    ------------------------------------------------------

    struct BCRSEntry* first_entry = row + sizeof(struct BCRSRow);
    struct BCRSEntry* last_entry = first_entry + row->length;

    hilft dir dass.

    EDIT:
    row->length = cols * mSizeOf_BCRSEntry;

    ich dennke so soll es sein.



  • also die beiden Strukturen BCRSRow und BCRSEntry werden beide mit 16 Byte Länge angezeigt.

    bei

    row =  malloc( length );
    

    fehlt nichts, da length als Variable vorher mittels der Makros oben ausgerechnet und gefüllt wird.

    Das Phänomen geht allerdings noch weiter: Ich konnte den Fehler weiter eingrenzen.
    Compiliert habe ich dieses Programm auf der Sun unter Solaris mittels:

    cc -g -o BSCR BCRS.c
    

    Der Fehler tritt auf wenn ich 600 Bytes in der Länge überschreite, verschwindet aber, wenn ich die Länge nicht mittels Makro ausreche sonders der Länge direkt in den malloc aufruf schreibe:

    row =  malloc( 10000 );
    

    zum Beispiel.

    Mit den GNU C-Compiler unter Ubuntu tritt der Fehler gar nicht auf. Mit dem funktioniert das programm ohne alle Probleme.

    gcc -g -o BCRS BCRS.c
    

    😕 😕

    Was könnte der Unterschied zwischen diesen beiden compilern sein?

    ----

    @Master.B: An die zwischenbytes habe ich auch schon gedacht. Aber würde dann nicht einfach nur mehr speicher angefordert werden? dann würde ich micht den dereferenzierungen zwar falsche Ergebnisse bekommen eventuell, aber ich würde im erlaubten Bereich bleiben.

    ---

    @Ramsis: Die BCRS Struktur arbeitet absichtlich nicht mit Pointern sondernd nur mit einem Item-Offset. Es handelt sich am Ende um eine Darstellung eines schwach besetzten Vektors, der allerdings in einem continuierlichem Speicherbereich gespeichert ist. Die row arbeitet dabei wie ein Puffer der Länge 'length' in der die Einträge des Vektors in Form einer einfach verketteten Liste gespeichert sind. die "leeren" Slots ebenfalls. So kann der Vektor dynamisch verändert werden ohne neu Speicher allozieren zu müssen.

    Der Grund warum nun nur Itemindizes und nicht direkte Pointer verwendet werden, obwohl diese schneller wären liegt daran, dass diese Vektoren im Zuge von Loadbalancing auf einem Cluster mit MPI einfach direkt ohne zusätzliche Puffer verschoben werden können unf am Zielnode ohne Verwaltungsaufwand direkt verwendwar sind.



  • stell mal im compiler das padding ab, und kuck was passiert!!

    typedef struct {
        int A,B,C;
    } BCRSRow;
    
    BCRSRow test;
    

    Mit padding wäre dieser zusammenhang nich immer gegeben:

    ((int*)&test)[0]== A
    ((int*)&test)[1]== B
    ((int*)&test)[2]== C
    


  • @ BorisDieKlinge:

    Wie kann ich das denn bei dem cc Compiler machen? Die Optionen lassen nicht darauf schliessen, dass hier ein Abschalten möglich wäre.

    Externer Link: cc Compileroptionen

    Was mich halt am meisten wundert ist, dass es mit length=1 bis 36 funktioniert.
    und wenn ich die Makros weglasse und viel größere werte reinschreibe bei malloc dann gehts auch 😡
    Mein reiner Maschinenverstand würde eigentlich sagen dass es, wenn es an padding liegen sollte, immer (nicht) gehen würde. Oder der Compiler mach Padding nur bei Strukturen bestimmter Längen.



  • Oder der Compiler mach Padding nur bei Strukturen bestimmter Längen.

    eben.. es hängt immer vom inhalt der Struktur ab, ob er padding macht... wobei dann die größe für jede struktur gleich bleibt!!

    length ist die anzahl der Bytes , und nich die anzahl de rstrukturen nehm ich an oder?

    was gibt er dir denn zurück wenn sizeof(...); machst????

    ich weis nur wie es beim VS 2003 abschalte1^^



  • auf der SUN haben beide Strukturen sizeof = 16;

    Demnach sollte es 'eigentlich' keinerlei Probleme beim Zugriff geben da keine ungeraden Adressen vorkommen und sogar alle offsets vielfache von 4 sind.

    ich werde es gleich mal mit der compileroption "-fpact-struct" versuchen von der ich in einem andren Forum gelesen hab, die aber auf der SUN seite nicht beschrieben steht. Mal sehen was dann passiert.

    Generell weiß ich aber nicht warum das padding überhaupt ein Problem darstellen sollte. Da ich den aktuellen Zeigen ja immer mit sizeof und der Strukturdereferenzierung berechne. Sizeof sollte das padding ja schon mit einrechnen und der Zugriff über -> auch.



  • stimmt eigentlich.. ich musst es mal berücksichtigen, als ich mit der puren bytesequen arbeitete



  • Naja.. vielen Dank erstmal an all, die sich hier beteilig haben bis jetzt!

    Ich werde mir erstmal einen anderen eigenen Arbeitsrechner suchen und damit leben dass das Programm so auf einer SUN-Architektir nicht läuft bis ich weiß warum.

    mit gcc auf x86 macht das Programm keine Probleme und ausgeführt werden soll es später eh auf einer x86 Architektur. Wäre nur halt schön wenn es auch für andere Architekturen compilierbar wäre.

    Den gcc konnte ich auf der SUN nicht ausprobieren da unsere Universität dort noch eine 1 vorne in der Versionsnummer hat und ich dann auch noch die Syntax ändern müßte 😡

    Falls hier doch noch mal jemand reinschaut, der weiß wie die SUN dinger ticken, der möge sich mal melden 🕶



  • hoch lebe die SUN-Architektur^^ 👎 👎



  • Ihr labert einen derben Müll in diesem Thread.



  • Weil du nichts verstehst.... bricht dein Studium ab hat keinen Sinn;)

    Dipl.Inf.Student Stolz: schrieb:

    Getroffene Hunde bellen



  • Dipl.Inf.Student schrieb:

    Ihr labert einen derben Müll in diesem Thread.

    Dann erleuchte uns mit deinem Wissen o Unbekannter, der Du uns Phrasen ohne jede Semantik hinterlaesst.

    ----

    Irgendwie ziehen Foren in denen Gaeste posten koennen immer magisch solche unqualifizierten Personen und ihr nutzlosen Kommentare an. 👎



  • NMCM schrieb:

    Dipl.Inf.Student schrieb:

    Ihr labert einen derben Müll in diesem Thread.

    Dann erleuchte uns mit deinem Wissen o Unbekannter

    Liefer du lieber mal einen sinnvollen Code. Das Dingens auf Seite 1 kompiliert doch bestimmt noch nichtmal...



  • ob das Beispiel auf Seite 1 Sinnvoll ist oder nicht ist egal wenn es ein Problem zu erklaeren vermag und ob es sich kompilieren laesst kannst du ganz einfach ausprobieren 😉



  • Ich brauch es nicht ausprobieren. Das kompiliert nicht. Du erwartest hoffentlich nicht mehr als Rumgerate um deinen Bug zu finden, wenn du kein sauberes minimales Beispiel liefern kannst, oder? Alleine schon main( char *argv, int *argc) 🙄



  • Ich wuerde nie behaupten ein super programmieren zu sein. Aber selbst weiss dass es nicht nur einen Weg gibt ein Problem zu loesen. Das Programm oben laesst sich bei mir problemlos mit dem SUN compiler compilieren. 😉 Und sogar das Problem konnte ich inzwischen loesen.

    Du scheinst dir deine Signatur aber etwas zu sehr zu Herzen zu nehmen. Ich haette lieber mit deinem kleinen Bruder geredet. 😃

    ----------
    Punkt.



  • NMCM schrieb:

    Du scheinst dir deine Signatur aber etwas zu sehr zu Herzen zu nehmen. Ich haette lieber mit deinem kleinen Bruder geredet.

    *lachmichschlapp*
    🙂



  • NMCM schrieb:

    Das Programm oben laesst sich bei mir problemlos mit dem SUN compiler compilieren. 😉

    Dann sag mir doch bitte woher z.B. der Compiler die Variable length in main() kennen soll? Held...


Anmelden zum Antworten