Komische Verhalten von Memory Allocationen für Pointer in einer Struktur



  • Ich habe eine Struktur:

    typedef struct DfaNode{
    ...
    struct DfaNode ** children;
    unsigned char ** symbols;
    size_t * symbolsizes;
    }
    

    Die Speicher für die Pointer allociere ich ja mit Malloc, und sogar am bei
    Initialisierung fällt mir was komisches an:

    ... 
    size_of_DfaNode = sizeof(DfaNode *);
     size_of_Ptr = sizeof (unsigned char *);
     size_of_size_t = sizeof(size_t);
    CHILDREN_DEF_AMOUNT = 4 ; // im code per macro , aber egal
    ...
    
    DfaNode * newDfaNode(...){
    	DfaNode * r_e_t;
    	r_e_t = (DfaNode *) malloc (size_of_DfaNode);
            ...
            	r_e_t->children = (DfaNode **) malloc(CHILDREN_DEF_AMOUNT *size_of_DfaNode );
    	r_e_t->symbols = (unsigned char **) malloc (CHILDREN_DEF_AMOUNT * size_of_Ptr);
    	r_e_t->symbolSizes = (size_t *) malloc (CHILDREN_DEF_AMOUNT * size_of_size_t);
    	return r_e_t;
    

    Bei Debugging in Eclipse, hat
    children eine Adresse 0x602030
    symbols 0x602060
    symbolSizes 0x602090

    aber der Erste Element ist schon initialisiert als
    *children = 0x602060. und zeigt auf 'symbols' was ist extrem falsch.
    die Erste Werte von anderen Arrays sind aber nullen:
    *symbols 0x0;
    *symbolSizes 0;

    Eine kann sagen, dass solche init spielt keine Rolle da weiter bei
    Hinzufügen von Children werden die Werte richtig gesetzt. Aber weiter passiert noch was komisches. Ich konstruiere einer Parent und füre ein Kind hinzu.
    Die Methode um ein Kind hinzufügen ist:

    DfaNode *addnewChildNode(DfaNode * parentNode, const char * outgoingSymbols, const size_t outgoingSymbolsLen){
    DfaNode * ret = newDfaNode (parentNode->delpth +1);
       // danach ist ret = 0x6020c0 und Werte sind richtig
       // das issue das *children auf symbols zeigt wiederholt hier aber.
    
    // .. hier habe ich Handling von eventuellen Reallocs was ist unwesentlich
    // da keine Reallocs bei diesem Test vorkommen können, ich sehe es auch von Debugging 
    
    parentNode->children[parentNode->childrenAmount] = ret;
    

    Und jetzt ist verkackt: weil children[0] ist auf ret = 0x6020c0 gesetzt und dabei wird aus unbekanntem Grund symbols auch auf diese Adresse gesetzt!
    Was ist ein Grund dafür, dass die children[0] und symbols werden so verbunden? 😮



  • o4kareg schrieb:

    ... 
    size_of_DfaNode = sizeof(DfaNode *);
     size_of_Ptr = sizeof (unsigned char *);
     size_of_size_t = sizeof(size_t);
    

    Wozu soll das denn bitte gut sein?

    DfaNode * newDfaNode(...){
    	DfaNode * r_e_t;
    	r_e_t = (DfaNode *) malloc (size_of_DfaNode);
    

    Der Cast ist überflüssig und die angeforderte Blockgröße zu klein. Da gehört sizeof(DfaNode) hin, nicht sizeof(DfaNode*). Oder noch besser: sizeof(*r_e_t).


  • Mod

    o4kareg schrieb:

    Ich habe eine Struktur:

    typedef struct DfaNode{
    ...
    struct DfaNode ** children;
    unsigned char ** symbols;
    size_t * symbolsizes;
    }
    

    Das sieht schon einmal komisch aus. Abgesehen vom fehlenden Semikolon, scheinst du nicht verstanden zu haben, wozu das typedef da ist. Abgeschrieben? Nachgemacht?

    Willst du wirklich Doppelzeiger? Klingt auch sehr verdächtig. Was soll das deiner Meinung nach repräsentieren? Ist jedenfalls schon auf halbem Weg zum Drei-Sterne-Programmierer:
    Google: three star programmer
    Merke: Abstraktion ist kein Feind, sondern macht dir das Leben wesentlich einfacher.

    Die Speicher für die Pointer allociere ich ja mit Malloc, und sogar am bei
    Initialisierung fällt mir was komisches an:

    ... 
    size_of_DfaNode = sizeof(DfaNode *);
    

    Dir ist klar, dass du hier die Größe eines Pointers nimmst (also meistens so 4 bis 8 Bytes)? Vermutlich nicht.

    Außerdem: Wenn das DfaNode zu der Definition von oben gehört, dann bedeutet dies, dass du vermutlich einen C++-Compiler für C benutzt hast.

    CHILDREN_DEF_AMOUNT = 4 ; // im code per macro , aber egal
    

    Wenn du Fehler hast, dann wäre es wichtig, dass du uns Code gibst, der nicht irgendwie so ähnlich ist, wie dein Code, sondern der dein Code ist und den Fehler noch zeigt. Siehe dritten Link in meiner Signatur (bitte wirklich angucken!). So könnte ich mir vorstellen, dass die Fehler, die ich oben angekreidet habe, durch falsches Abschreiben zustande gekommen sind (denn das oben sollte gar nicht compilieren). In dem Fall hättest du zumindest schon einmal meine Zeit unnütz verschwendet.

    Wieso überhaupt malloc, wenn CHILDREN_DEF_AMOUNT eine Konstante ist?

    r_e_t = (DfaNode *) malloc (size_of_DfaNode);
    

    Wieder etwas, das ganz stark nach C++-Compiler riecht. Der Cast hat in C nichts zu suchen. C++ und C sind nicht wirklich kompatibel, auch wenn man es gerne so sagt. Komplexere Programme als Hello-World sind nicht von C nach C++ übertragbar. Die Regeln für Pointerumwandlungen sind in C++ ganz anders!

    ...
            	r_e_t->children = (DfaNode **) malloc(CHILDREN_DEF_AMOUNT *size_of_DfaNode );
    	r_e_t->symbols = (unsigned char **) malloc (CHILDREN_DEF_AMOUNT * size_of_Ptr);
    	r_e_t->symbolSizes = (size_t *) malloc (CHILDREN_DEF_AMOUNT * size_of_size_t);
    

    Siehe oben.

    [weitere Fehlerbeschreibung]

    Bitte nimm erst einmal Stellung zu dem, was ich zu dem Code gesagt habe. Der Code muss sauber ohne Warnungen auf einem C-Compiler übersetzbar sein, dann kann man eventuell weitere Fehler suchen. Solange noch offensichtliche technische Fehler im Code sind, braucht man gar nicht erst mit dem Debuggen anzufangen.



  • Die Casts sind ja voll egal, einfach dass man weniger Warnings hat 😃

    Da gehört sizeof(DfaNode) hin, nicht sizeof(DfaNode*). Oder noch besser: sizeof(*r_e_t).

    Ja das war das Problem, irgendwie den falshes Size hat o.g. Problem ausgelösst und jetzt ist alles ok. Danke sehr dass du SOLCHEN Bug 🤡 so schnell gefunden hast.

    Kleiner Offtopic:

    Die Regeln für Pointerumwandlungen sind in C++ ganz anders!
    

    Wie denn?

    Bez. 3 Stern - dann ist ein Pthreads- Programmierer ein Generallisimus bei nützten mancher Funktionen, wie: void (void (void*)(blablabla...) ...)


  • Mod

    o4kareg schrieb:

    Die Casts sind ja voll egal, einfach dass man weniger Warnings hat 😃

    Wenn du da eine Warnung hast, dann ist da ein Fehler. Der Cast sagt dem Compiler, dass er trotzdem die Schnauze halten soll. Vermutlich hast du vergessen stdlib.h einzubinden. Das wird dir nun auf einem 64-Bit System mit hoher Wahrscheinlichkeit explodieren. Merke: Niemals durch Casts Warnungen abstellen.

    Bitte nimm auch zu meinem Beitrag Stellung. Bloß weil ich deinen Code runtermache, heißt das nicht, dass ich dir was böses will. Ich mache dich bloß auf die vielen Fehler aufmerksam, die nun einmal ganz objektiv in dem Code vorhanden sind. Nur dadurch kann der Code besser werden, nicht indem man Fehler durch Casts vertuscht.



  • o4kareg schrieb:

    Danke sehr dass du SOLCHEN Bug 🤡 so schnell gefunden hast.

    Solche Bugs sind total einfach zu finden.


Anmelden zum Antworten