Inhalt eines Char-Zeigers einem String zuweisen



  • Ok danke für den Tipp der Speicherfreigabe.

    Strings gehen nicht, da ich auf Funktionen zugreife, die ich nicht zu verantworten habe und die char-Zeiger erwarten.

    mfg chuqa



  • Also irgendwie hab ich eigentlich nix gemacht, trotzdem tritt der Fehler jetzt nichtmehr an der Stelle der Zuweisung an die Map auf sondern schon beim ersten Lesen der Variable innerClass nach der Funktion. In der Funktion passiert mit der Variable eigentlich nix anderes als eine Wertzuweisung, die auch erfolgreich ist:

    int fcInnerClassRef(char *target, char *p_outerClass, char *baseName, char *member){
        ...
        strncpy((char*)target, p_innerClass, FC6_MAX_NAME_LEN);
        cout << "target: " << target << endl;
        return 0;
    }
    

    Und genau der erste Aufruf von innerClass funktioniert nicht, auch wenn ich an der Stelle des Aufrufs mir den Wert von der Variable mit dem Debugger ausgeben lasse, kommt nur

    $1 = 0x0

    . Also irgendwie wird der Wert dort nicht zugewiesen.



  • Verwende bitt string in einer map. Wenn andere Funktionen char* brauchen, mußt du eben wieder umwandeln (mit c_str() oder kopieren).
    Sowas hier

    ref_mapDrv["ifaceParamClass"] = innerClass;
    free(innerClass);
    

    ist tödlich. Selbst wenn statt free hier delete[] steht wird der Pointer in der map ungültig und jeder weitere Zugriff erzeugt undefieniertes Verhalten.



  • Chuqa schrieb:

    ... diesen Wert einer map<string,string> zuzuweisen

    Er benutzt std::string in der Map, also wird korrekt (=tief) kopiert.

    Chuqa schrieb:

    int fcInnerClassRef(char *target, char *p_outerClass, char *baseName, char *member){
        ...
        strncpy((char*)target, p_innerClass, FC6_MAX_NAME_LEN);
        cout << "target: " << target << endl;
        return 0;
    }
    

    Der Code ist, soweit ich das sehe richtig. Schau mal, wo target den Nullzeiger zugewiesen bekommt. (Und mehr Code ...)



  • Also habe mal alle delete entfernt, hatte auch zu Testzwecken innerClass als string deklariert und eine Referenz auf diesen String der Funktion fcInnerClassRef übergeben, passiert aber genau das gleiche.
    Ich weise target nirgends den Nullzeiger zu, deklariere innerClass als char-Zeiger und übergebe ihn der Funktion fcInnerClassRef();
    Mehr Code gibt es einfach nicht, der die Variablen betrifft. Ich deklariere das Array im Heap, übergeben einen Zeiger auf das Array an die Funktion, dort wird der Wert verändert (die Ausgabe von target in der Funktion ist korrekt) und versuche nach Verlassen der Funktion erneut auf den Zeiger zuzugreifen, welches mir ein Memory fault liefert.

    int fcInnerClassRef(char *target, char *p_outerClass, char *baseName, char *member){
        ...
        strncpy((char*)target, p_innerClass, FC6_MAX_NAME_LEN);
        cout << "target: " << target << endl;
        return 0;
    }
    void installIface(map<string, string> &ref_mapDrv,      // g
                    map<string, string> &ref_mapParams,     // 
                    driverparam &ref_drvParam,              //
                    driverparam &ref_param_parseParaDef,    //
                    baseInterface &ref_baseIface)           // dp
    {
        ...	
        char *innerClass = new char [FC6_MAX_NAME_LEN +1];
        innerClass[0] = '\0';
        fcInnerClassRef(innerClass, p_c, "_ParamList", "paramlist");
        cout << "innerClassRef: " << innerClass << endl;    // FEHLER
        ...
    }
    

    Das ist eigentlich alles, wenn du etwas bestimmtes noch haben möchtest, sage bescheid.

    mfg chuqa



  • Woher kommt denn die Variable p_innerClass die in der Funktion kopiert wird? Ist diese vielleicht zu lang, so dass FC6_MAX_BLA nicht reicht, oder nicht initialisiert, oder nicht nullterminiert, oder...?

    Du siehst, es war nicht alles relevante dabei 😉



  • Dafür ist doch strncpy da, oder? Aber der Zeiger scheint ja laut Debugger den Wert 0 zu haben (oder ist das der dereferenzierte Zeiger?!). Wird innerhalb des ominösen ...-Bereichs noch in irgendeiner Art und Weise auf den Zeiger zugegriffen?



  • Hups, habe dieses kleine n doch glatt übersehen 😮



  • Nein auf den Zeiger wird vorher nicht zugegriffen, das ist der erste Zugriff. Leider sind meine Erfahrungen mit Zeiger sehr begrenzt, deswegen hoff ich auf eure Hilfe.



  • Vielleicht wäre es besser, den kompletten Code von fcInnerClassRef anzugeben.
    Was soll übrigens dieser char*-Cast von Target in dieser Funktion?



  • Was der Typecast sollte, weiß ich auch nicht, ändert nur leider nix am Fehler. Also wenn ich die Funktion poste, muss ich das halbe Programm vermutlich dazu posten, welches im Moment ca. 2000 Zeilen umfasst. Und dann darf ich das leider nicht, denn das was ich hier schreibe ist für meinen Praxispartner und deswegen Eigentum von ihm. p_innerClass ist auch ein Array, welches im Heap liegt und die gleiche Größe wie bereits innerClass hat. Die Werte die in den Arrays geschrieben werden, sind aber deutlich kleiner als als die definierte Größe.
    Was eben mich nur wundert,ist,dass target den korrekten Wert hat und innerClass nicht, dabei sind das doch dieselben Variablen, oder nicht?



  • Es dreht sich hier erstmal bloß um fcInnerClassRef. Falls da irgendwo vorher target auf 0 gestzt wird, oder eine lokale Variable namens target den Parameter überdeckt kann sowas auftrteten. Geh doch mal mit deinem Debugger durch und schau dir target an.



  • So bin grad das Programm mit einem Debugger durchgegangen und habe mir die betroffene Variable angeschaut. Ich poste mal die Ausgaben und die Stellen im Quellcode(mit p <variable> kann ich mir den Wert der Variablen ausgeben lassen):

    /* Bei Aufruf von fcInnerClassRef()
    fcInnerClassRef(innerClass, p_c, "_ParamList", "paramlist");
    p innerClass */
    $17 = 0x81c5c90 ""
    /* in fcInnerClassRef unmittelbar zu Beginn
    p target */
    $18 = 0x81c5c90 ""
    /* unmittelbar vor strncpy
    strncpy(p_target, p_innerClass, FC6_MAX_NAME_LEN);
    p target */
    $20 = 0x81c5c90 "
    /* unmittelbar nach strncpy */
    strncpy(p_target, p_innerClass, FC6_MAX_NAME_LEN);
    p target */
    $21 = 0x81c5c90 "/fc6demo.Devices.Classes._ParamList._ParamList0x0000010C"
    /* bei return aus fcInnerClassRef
    p target */
    $22 = 0x81c5c90 "/fc6demo.Devices.Classes._ParamList._ParamList0x0000010C"
    /* unmittelbar nach verlassen von fcInnerClassRef() in installIface()
    p innerClass */
    $23 = 0x0

    also so wie es aussieht wird dem Zeiger innerClass nach Verlassen der Funktion der Nullzeiger zugewiesen, aber warum?



  • Hmm, wer hat denn noch alles Zugriff auf innerClass? Vielleicht gibts irgendeinen Destruktor, der das zurücksetzt. Wir brauchen mehr Code. Zeig mal welche Objekte in fcInnerClassRef deklariert werden.



  • char *baseNameCnt = new char [FC6_MAX_NAME_LEN+1];
    char *p_nn = new char [100];
    int nn;
    char *p_innerClass = new char [FC6_MAX_NAME_LEN +1];
    char c_nn [20];
    char *p_innerClassGroup = new char [FC6_MAX_NAME_LEN + 1];
    char *ref_argv[6];
    int size_refArgv = sizeof(ref_argv)/sizeof(char*);
    


  • Setze doch mal vor Aufruf von fcInnerClassRef einen watchpoint auf die Variable innerClass, dann stoppt der Debugger sowie sich der Inhalt dieser Variable ändert.

    So hab ich schon manches Mysterium dieser Art lösen können 😉



  • Gebe ich als Watchpoint innerClass an, dann unterbricht mir der Debugger nur an der Stelle der Deklaration:

    /*char *innerClass = new char [FC6_MAX_NAME_LEN +1];*/
    Old value = 0xb031e654 "\215eè[^_ÉAU\211å\213E\bÉAU\211å\203ì\fWVSè"
    New value = 0x81c5c90 ""

    Gebe ich noch target als watchpoint an und gehe in die Funktion fcInnerClassRef(), dann stoppt der Debugger beim return mit der Meldung:

    Watchpoint 16 deleted because the program has left the block in
    which its expression is valid.

    Watchpoint 18 deleted because the program has left the block in
    which its expression is valid.

    , wobei Watchpoint 16 auf innerClass und Watchpoint18 auf target liegt.

    Habe gerade noch festgestellt, dass noch mehr Variablen ihren Speicherbereich verlieren. Habe testhalber einmal watchpoints auf die Parameter der Funktion installIface() gesetzt, aber auch die verlieren ihre Gültigkeit. Wie ist das möglich?



  • Hm, das macht mein gdb auch ganz gerne (obwohl innerClass ja nichts mit dem Stack Context von fcInnerClassRef zu tun hat)... ich helfe mir dann immer mit:

    (gdb) p &innerClass
    $1 = (char **) 0xbffff3d4
    (gdb) watch *((char**)0xbffff3d4)
    Hardware watchpoint 2: *(char **) 3221222356
    

    Klar, dass es einen Break bei der Zuweisung des Speicherbereichs gibt. Wenn er jetzt immernoch nicht die Stelle findet, fange ich an an Voodoo zu glauben.



  • hmm ich denke deine Voodoo-Glaube nimmt langsam Gestalt an, habe es so gemacht, wie du es beschrieben hattest, aber das gleiche Ergebnis: break bei Deklaration, erneutes continue, Meldung dass das Programm abgestürzt ist (Program received signal SIGSERV), es ist nur sehr sonderbar, dass auch bei die Parameter keine Speicheradresse mehr haben, nachdem das Programm aus fcInnerClassRef() zurückkehrt.



  • Also Jungs, der Fehler ist gefunden! 😃
    Er war alelrdings an einer ganz anderen Stelle, und zwar wurde in der Funktion fcInnerClassRef eine weitere Funktion aufgerufen, die wiederum die Funktion itoa() enthält. Mein Fehler war, dass ich versucht habe, einer Stelle in einem Array aus Char-Zeigern mithilfe dieser Funktion einen nummerischen Wert als char schreibe. Das Problem ist nur, dass ich diese Stelle bereits vorher einen const char-Wert zugewiesen habe:

    char *argv[5];
    argv[0] = "";
    argv[1] = path;
    argv[2] = target_rootCmd;
    argv[3] = "-classtype";
    argv[4] = "deviceobject";
    ...
    argv[0] = "";
    argv[1] = path;
    argv[2] = "configure";
    argv[3] = "-value";
    itoa(tmpval, argv[4], 10);
    ...
    

    Damit ging es natürlich nicht. Die Verbesserung lautet:

    char buffer[10];
    itoa(tmpval, buffer, 10);
    argv[4] = buffer;
    

    Nach viel Nerven, der halben Firma, die sich den Kopf zerbrochen hat, zeilenweises auskommentieren bzw. include von Code und natürlich euerer Hilfe wurde diese Stelle nun gefunden. Ich danke euch alle ganz herzlich für die aufopfernde Hilfe 😉

    mfg chuqa


Anmelden zum Antworten