Zeiger verschwindet ... was mach ich falsch?!



  • Moin moin,
    ich bin noch ziemlicher newbie in Sachen Zeiger. Hab' es schon mit der Suche versucht, wusste aber leider nicht, wie ich einen richtigen Suchbegriff finde.

    Jedenfalls folgendes Problem. Ich bekomme aus einer Schnittstelle irgendwelche void-Zeiger, in denen irgendwelche structs verbastelt sind.
    Im Header steht dann z.B.:

    // in irgendeinem Header einer c-Schnittstelle
    typedef struct
    {
        unsigned int year;
        unsigned int month;
        unsigned int dayOfMonth;
        unsigned int dayOfWeek;
    } STRUCT_DATE;
    

    Jetzt will ich diese void Zeiger auspacken. Da sind dann einzelne oder mehrerer solcher structs drin. Es können alle möglichen kommen, also habe ich für jeden möglichen struct (das oben ist nur ein Beispiel) so eine Funktion gebaut:

    STRUCT_DATE create_STRUCT_DATE(unsigned int index,void* pvoid)
    {
    	STRUCT_DATE* adr = (STRUCT_DATE*) pvoid;
    	return adr[index];
    }
    

    Dazu dann diese Klasse:

    class Date
    {
    private:
    	STRUCT_DATE pemDate;
    public:
    	STRUCT_DATE get_Date() { return pemDate; };
    	void set_Date(STRUCT_DATE date) { pemDate = date; };
    	// ....
    
    	Date(unsigned int index, void* pdat);
    
    };
    
    Date::Date(unsigned int index, void* pdat)
    {
    if (pdat != 0)
    	pemDate = create_STRUCT_DATE(index,pdat);
    
    }
    

    Wenn ich nur folgenden Aufruf starte:

    // ... pvoid ist void* mit Inhalt STRUCT_DATE
    Date* theDate = new Date(0,pvoid);
    

    dann habe ich im Konstruktor noch den pdat und index so, wie ich sie übergeben habe, aber in create_STRUCT_DATE ist pvoid = 0 und index irgendwas Grosses.

    Woran kann sowas liegen?! 😕

    Danke im Voraus für Eure Mühe.

    Greetz,
    Qweety.



  • STRUCT_DATE create_STRUCT_DATE(unsigned int index,void* pvoid)
    {
    	STRUCT_DATE* adr = (STRUCT_DATE*) pvoid;
    	return adr[index];
    }
    

    Du legst den Pointer adr in der Funktion an, d.h. er ist auch nur in der Funktion gültig. Wenn du ihn zurückgibst, verlässt du den Sichtbarkeitsbereich/Gültigkeitsbereich/Scope/nenns wie du willst und der Pointer wird ungültig.



  • Michael E. schrieb:

    Du legst den Pointer adr in der Funktion an, d.h. er ist auch nur in der Funktion gültig. Wenn du ihn zurückgibst, verlässt du den Sichtbarkeitsbereich/Gültigkeitsbereich/Scope/nenns wie du willst und der Pointer wird ungültig.

    Hi Michael,
    vielen Dank für Deine Antwort.

    Das Problem tritt aber schon im Aufruf der Funktion auf. Schon bevor ich die Zeile

    STRUCT_DATE* adr = (STRUCT_DATE*) pvoid;
    

    überhaupt ausführe, sind die Übergabeparameter der Funktion schon kaputt.

    Lustiger Weise funktioniert das Folgende ohne Probs:

    // in irgendeinem Header einer c-Schnittstelle
    typedef struct
    {
        unsigned long year;
        unsigned int month;
        unsigned int dayOfMonth;
        unsigned int dayOfWeek;
    } STRUCT_DATE2;
    
    STRUCT_DATE2 create_STRUCT_DATE2(unsigned int index,void* pvoid)
    {
        STRUCT_DATE2* adr = (STRUCT_DATE2*) pvoid;
        return adr[index];
    }
    

    Leider kann ich ja dem Menschen, der die Lib geschrieben hat, nicht einfach bitten, sein struct zu ändern und in seinem Zeiger steht nun mal die erste Variante.

    Wie kann sowas sein? Ich habe es zig mal ausprobiert. Es scheint wirklich am Rückgabetyp der Funktion zu liegen. Er akzeptiert alles andere an Rückgabetypen (einfache und structs), nur wenn das struct mit einem unsigned int beginnt, steigt er aus.
    Da habe ich doch bestimmt irgendwas anderes übersehen.

    ------------------------------------------

    Aber um auf Deinen Hinweis zurück zu kommen.
    Ist der Pointer adr nicht eigentlich nur ein cast von pvoid. Die wirkliche Speicheradresse wird also doch nicht ungültig, oder?

    Wäre denn das Folgende richtiger?

    STRUCT_DATE create_STRUCT_DATE(unsigned int index,void* pvoid)
    {
        STRUCT_DATE* adr = (STRUCT_DATE*) pvoid;
        STRUCT_DATE ret = adr[index];
        return ret;
    }
    

    Irgendwie wird bei einem return doch jede lokale Variablenbezeichnung ungültig.
    Oder wird bei
    STRUCT_DATE ret = adr[index];
    auch wieder nur ein Pointer zugewiesen? Ich dachte, structs würden eher wie Datentypen behandelt.

    Wenn ich z.B. das Folgende mache

    struct atest
    {
        int i;
        bool b;
        int* arri;
        bool* arrb;
    };
    
    //...
    atest test;
    test.i = 5;
    test.b = true;
    test.arri = new int[2];
    test.arrb = new bool[2];
    
    atest test2 = test;
    

    Dann sind in test2 i und b eigentlich richtig belegt und die beiden arrays sind natürlich Schrott. Wenn ich aber im struct nur einfache Datentypen habe, sollte es dann nicht funktionieren?

    Gruss,
    Qweety.



  • Hi

    Irgendwie wird bei einem return doch jede lokale Variablenbezeichnung ungültig.
    Oder wird bei
    STRUCT_DATE ret = adr[index];
    auch wieder nur ein Pointer zugewiesen? Ich dachte, structs würden eher wie Datentypen behandelt.

    Das kann eigentlich nicht sein, dann würdest du auch nen pointer auf den anfang eines arrays von pointern auf die strukturen übergeben bekommen.
    Es wird eben ne kopie zurück gegeben. Das geht schon.

    Kannst du mal den code vor Date* theDate = new Date(0,pvoid); posten ?
    Wo z.B. pvoid initialisiert wird oder wenns irgendwo anders herkommt, woher.



  • Hi prolog

    prolog schrieb:

    Kannst du mal den code vor Date* theDate = new Date(0,pvoid); posten ?
    Wo z.B. pvoid initialisiert wird oder wenns irgendwo anders herkommt, woher.

    oh, das wird irgendwo in einer wilden Bibliothek zur Verfügung gestellt, ich hab eigentlich nur den Header mit den structs.
    Also ich rufe eine Funktion auf, der ich so ein RESULT_SET hier übergebe:

    typedef struct
    {
      unsigned long                        propertyId;    // one out of PROPERTY_ID
      unsigned long                        propertyIndex; // array index element access
      unsigned int                        fErrorPresent; // if set "propertyError" is valid
    	RESULT_ERROR             propertyError; // contains the UCInet error
    	RESULT_PROPERTY_CONTENTS propertyValue; // contains the UCInet value
    } RESULT;
    
    typedef struct
    {
    	BYTE             fFirstItemPresent; // first requested item is present
    	BYTE             fLastItemPresent;  // last requested item is present
    	BYTE             fMoreItemsPresent; // more items than requested are present
    	UINT             numberOfResults;   // number of entries in "result"
    	RESULT *result;           // property description and value
    } RESULT_SET;
    

    Ich muss nur das struct übergeben, die Bibliothek sorgt für die Speicherzuordnung. Wenn ich dann mit meiner Bearbeitung fertig bin, habe ich eine Funktion, der ich das gefüllte struct wieder übergebe und die Bibliothek räumt es dann auf. Den Zeiger bekomme ich in RESULT_PROPERTY_CONTENTS , das sieht so aus:

    typedef struct
    {
        unsigned int type;	 // type of data contents in this buffer
        unsigned int nElements;	 // number of elements in this buffer
        unsigned  bufferSize;   // size of buffer
        void *bufferData;  // decoded UCInet value (c-structs...)
    } PROPERTY_CONTENTS;
    

    Und das bufferData ist besagtes pvoid.
    Anhand von type und nElements weiss ich, wie viele structs von welchem Typ da drin sind.
    Im vorliegenden Fall war nElements = 1 und der Wert von type wies das Ganze als Datum aus. Laut Referenz halt mit der angegebenen Struktur.

    Der Code ist da recht wenig sagend *befürcht*:

    //c-Lib
    #include "UCIclient.h" // <- hier ist die Schnittstelle drin z.B. STRUCT_DATE
    #include "MyBuisness.h" // hier sind die eigenen Sachen drin z.B. class Date und create_STRUCT_DATE
    
    int main()
    {
    	RESULT_SET resset;
    	resset.numberOfResults = 0;
    	resset.result = 0;
    	UCICLIENT_ERRORS erg = (UCICLIENT_ERRORS )UCIGetPropertyList(0,0,&resset); // 0,0 bedeutet, ohne Filter alles lesen
    
    	if (erg == UCICLIENT_ERROR::OK)
    	{
    		if (res)
    			for (unsigned int i = 0; i < resset.numberOfResults; ++i)
    			{
    				RESULT result = resultset.result[i];
    				PROPERTY_CONTENTS propval = result.propertyValue;
    				void* pvoid = propval.bufferData;
    
    				switch (propval.type)
    				{
    					// ...
    
    					case UCI_DATA_TYPES::DATA_TYPE_DATE:
    					{
    						if (propval.nElements == 1)
    						{
    							Date* theDate = new Date(0,pvoid); 
    							// Alles mögliche mit dem Datum tun
    						}
    						else
    						{
    							// TODO ...
    						}
    
    					}
    					break;
    
    					// ...
    
    					default:
    					// ...
    					break;
    				} // switch
    			} // for
    			UCIReleaseResult(&resset); // Result-Set aufräumen
    	}
    	else // if erg
    	{
    		// ...
    		// Fehlerbehandlung
    	} // else erg
    
    	// ...
    
    	return 0;
    }
    

    UCI ist eine statische Bibiothek und ich habe nur die Schnittstelle und die lib. Ich hoffe, ich habe alles 'rübergekriegt, was Dich interessiert, weil das sind ein paar huntert Zeilen Code und ich wollte es auf das Wesentliche reduzieren. Ist nur 'nen Testprog, um zu schauen, ob ich überhaupt was in dem Zeiger lesen kann und nur beim Datum macht er diesen Terror.
    Und wie erwähnt mit dem Returntyp. Habe es hin und her gedreht. Sobald die Create_XYZ Funktion ein struct zurückgeben soll, dass mit "unsigned int" anfängt, ist der Zeiger in der aufgerufenen Funktion 0. Noch lustiger, ich hab' dann gemerkt, dass der index den Wert der Adresse hat, auf die pvoid eigentlich zeigt. Da hat er doch aus irgendeinem Grund die Parameterliste verschoben, oder wie?

    Gruss,
    Qweety.



  • Qweety schrieb:

    Hi prolog

    prolog schrieb:

    Kannst du mal den code vor Date* theDate = new Date(0,pvoid); posten ?
    Wo z.B. pvoid initialisiert wird oder wenns irgendwo anders herkommt, woher.

    oh, das wird irgendwo in einer wilden Bibliothek zur Verfügung gestellt, ich hab eigentlich nur den Header mit den structs.
    Also ich rufe eine Funktion auf, der ich so ein RESULT_SET hier übergebe:

    typedef struct
    {
      unsigned long                        propertyId;    // one out of PROPERTY_ID
      unsigned long                        propertyIndex; // array index element access
      unsigned int                        fErrorPresent; // if set "propertyError" is valid
    	RESULT_ERROR             propertyError; // contains the UCInet error
    	PROPERTY_CONTENTS propertyValue; // contains the UCInet value
    } RESULT;
    
    typedef struct
    {
    	unsigned int             fFirstItemPresent; // first requested item is present
    	unsigned int             fLastItemPresent;  // last requested item is present
    	unsigned int              fMoreItemsPresent; // more items than requested are present
    	unsigned int             numberOfResults;   // number of entries in "result"
    	RESULT *result;           // property description and value
    } RESULT_SET;
    

    Ich muss nur das struct übergeben, die Bibliothek sorgt für die Speicherzuordnung. Wenn ich dann mit meiner Bearbeitung fertig bin, habe ich eine Funktion, der ich das gefüllte struct wieder übergebe und die Bibliothek räumt es dann auf. Den Zeiger bekomme ich in RESULT_PROPERTY_CONTENTS , das sieht so aus:

    typedef struct
    {
        unsigned int type;	 // type of data contents in this buffer
        unsigned int nElements;	 // number of elements in this buffer
        unsigned  bufferSize;   // size of buffer
        void *bufferData;  // decoded UCInet value (c-structs...)
    } PROPERTY_CONTENTS;
    

    Und das bufferData ist besagtes pvoid.
    Anhand von type und nElements weiss ich, wie viele structs von welchem Typ da drin sind.
    Im vorliegenden Fall war nElements = 1 und der Wert von type wies das Ganze als Datum aus. Laut Referenz halt mit der angegebenen Struktur.

    Der Code ist da recht wenig sagend *befürcht*:

    //c-Lib
    #include "UCIclient.h" // <- hier ist die Schnittstelle drin z.B. STRUCT_DATE
    #include "MyBuisness.h" // hier sind die eigenen Sachen drin z.B. class Date und create_STRUCT_DATE
    
    int main()
    {
    	RESULT_SET resset;
    	resset.numberOfResults = 0;
    	resset.result = 0;
    	UCICLIENT_ERRORS erg = (UCICLIENT_ERRORS )UCIGetPropertyList(0,0,&resset); // 0,0 bedeutet, ohne Filter alles lesen
    	
    	if (erg == UCICLIENT_ERROR::OK)
    	{
    		if (res)
    			for (unsigned int i = 0; i < resset.numberOfResults; ++i)
    			{
    				RESULT result = resultset.result[i];
    				PROPERTY_CONTENTS propval = result.propertyValue;
    				void* pvoid = propval.bufferData;
    				
    				switch (propval.type)
    				{
    					// ...
    
    					case UCI_DATA_TYPES::DATA_TYPE_DATE:
    					{
    						if (propval.nElements == 1)
    						{
    							Date* theDate = new Date(0,pvoid); 
    							// Alles mögliche mit dem Datum tun
    						}
    						else
    						{
    							// TODO ...
    						}
    					
    					}
    					break;
    
    					// ...
    
    					default:
    					// ...
    					break;
    				} // switch
    			} // for
    			UCIReleaseResult(&resset); // Result-Set aufräumen
    	}
    	else // if erg
    	{
    		// ...
    		// Fehlerbehandlung
    	} // else erg
    	
    	
    	// ...
    	
    	return 0;
    }
    

    UCI ist eine statische Bibiothek und ich habe nur die Schnittstelle und die lib. Ich hoffe, ich habe alles 'rübergekriegt, was Dich interessiert, weil das sind ein paar huntert Zeilen Code und ich wollte es auf das Wesentliche reduzieren. Ist nur 'nen Testprog, um zu schauen, ob ich überhaupt was in dem Zeiger lesen kann und nur beim Datum macht er diesen Terror.
    Und wie erwähnt mit dem Returntyp. Habe es hin und her gedreht. Sobald die Create_XYZ Funktion ein struct zurückgeben soll, dass mit "unsigned int" anfängt, ist der Zeiger in der aufgerufenen Funktion 0. Noch lustiger, ich hab' dann gemerkt, dass der index den Wert der Adresse hat, auf die pvoid eigentlich zeigt. Da hat er doch aus irgendeinem Grund die Parameterliste verschoben, oder wie?

    Gruss,
    Qweety.



  • Sorry, die Bedienung der Editiertfunktion war mir nicht geläufig.


Anmelden zum Antworten