Rückgabe Variant



  • 🙄

    Nochmals Entschuldigung dass ich im falschen Unterforum gelandet bin.

    Vieleicht könnte man auch ein Unterforum aufmachen in dem man über falsche Forumseinträge diskutieren kann. Einfach das Thema dort reinkopieren. Wem es dann Spaß mach sich seinen Tag so zu vertreiben, bitte.

    Vieleicht hier nochmals höfflichst die Frage:

    Kann mir jemand zu meiner Eingangsfrage helfen?



  • Aus der Dokumentation zu VariantInit bzw. VariantClear entnehme ich, dass Du nichts weiter tun musst, solange Du einen Doublewert in Deiner VARIANT-Variable aufbewahrst.
    Du kannst die Variable einfach per Zuweisung kopieren, oder wie in Deinem Fall durch Rückgabe als Funktionswert.



  • Da laut Doku VariantInit() bloß VARIANT::vt auf VT_EMPTY setzt, du VARIANT::vt aber eh gleich für deine Bedürfnisse änderst, glaube ich nicht, daß du die Funktion aufruffen musst.



  • meinard schrieb:

    3. Was passiert wenn ich einen VARIANT zurückgebe

    Einen VARIANT kannst du nicht zurückgeben, das ist unmöglich. Lern Grundlagen.



  • Einen VARIANT kannst du nicht zurückgeben, das ist unmöglich. Lern Grundlagen.

    Wieso ist das unmöglich mache ich doch in dem Beispiel und funktioniert ja auch.



  • Das machst du nicht. Wenn es funktioniert, dann zufällig. Beachte, dass IMMER (bei x86) eax den Rückgabewert enthält. eax ist 4 Bytes groß, VARIANT ist deutlich größer.



  • So ein Blödsinn!
    Dann kann man wohl auch keinen double zurückgeben, geschweige denn Instanzen von beliebigen Klassen?



  • ach wie [d|t]rollig 🙄



  • Nochmals die Frage

    Wann muss man VariantInit aufrufen und wann VariantClear.
    Wass passiert wenn ich einen Variant kopiere sei es mit dem Zuweisungsoperator oder VariantCopy

    muss ich dann VariantClear auf auf den SourceVariant sowie auf den DestVariant VariantClear aufrufen.



  • Wass passiert wenn ich einen Variant kopiere sei es mit dem Zuweisungsoperator oder VariantCopy muss ich dann VariantClear auf auf den SourceVariant sowie auf den DestVariant VariantClear aufrufen.

    VariantCopy -> 2mal VariantClear, sonst eventuell memory leak
    einfache Zuweisung -> nur einmal, sonst eventuell undefined behaviour / Crash

    Das hängt aber auch davon ab, was in dem Variant drin steckt.
    Bei trivialen Sachen wie double, float, int, ... kann man auch einfach zuweisen und niemals VariantClear oder VariantCopy verwenden. Wenn in dem Variant Strings (VT_BSTR) oder Arrays oder so drin sind oder man nichts genaues weiss, dann sollte besser man VariantCopy usw. verwenden. Oder eben selbst den Speicher korrekt handeln.

    Wann muss man VariantInit aufrufen und wann VariantClear.

    VariantInit setzt den Variant auf empty. Ansonsten kann VariantClear crashen. (Statt VariantInit den vt manuell setzen reicht auch aus). Ansonsten siehe oben. Muss man nie verwenden. Aber bei nicht trivialem Inhalt ist VariantClear (und VariantCopy) praktisch.

    P.S.: In C++ sollte man am besten einen Wrapper um den Variant verwenden. Sowas wie COleVariant.



  • Du brauchst die ...Init / ...Clear - Funktionen frühestens dann, wenn Deine Variable irgendeinen Pointer beherbergt. Solange Du da einen double - Wert drin aufbewahrst, kannst Du Deine VARIANT - Variable behandeln, wie jede andere auch!



  • Hallo _cu hallo Belli, danke für eure konkrete Hilfe

    Meine Variants beinhalten ausser int, double, float, auch BStr.
    Der macht mir dann auch am meisten Sorgen.

    Um auf Nummer sicher zu gehen würde ich am liebesten immer VariantCopy verwenden.
    Mein Problem ist hier aber der Rückgabewert.

    Wenn ich einen VARIANT zurückgebe ist dies eine Kopie ohne VariantCopy

    Hier nochmals ein Beispiel mit CString

    virtual VARIANT GetVariantValue() const
    {
    VARIANT variant;
    VariantInit(&variant);

    variant.vt = m_varianttype;
    CString csvalue = Value;
    variant.bstrVal = csvalue.AllocSysString();

    return variant;
    }

    Wann muss ich hier VariantClear aufrufen?


  • Mod

    VariantClear musst Du anwenden, wenn Du Deinen VARIANT nicht mehr brauchst.
    Eigentlich ist immer der verantwortlich, der ein VARIANT erhält.

    Einfacher ist die Verwendung von CComVariant (oder COleVariant). Die kapseln das für Dich.

    Dann geht auch die Initialisierung "wie von selbst"

    Solchen Code halte ich für nicht gut.

    variant.vt = m_varianttype; 
    	CString csvalue = Value; 
    	variant.bstrVal = csvalue.AllocSysString();
    

    Wenn Du schon klar einen VT_BSTR zuweist, dann solltest Du auch VT_BSTR direkt setzen. Und höchstens vorher noch einen ASSERT Test machen.

    ASSERT(m_varianttype==VT_BSTR);
    

    Bitte verwende Codetags.



  • Hi Martin

    VariantClear musst Du anwenden, wenn Du Deinen VARIANT nicht mehr brauchst.
    Eigentlich ist immer der verantwortlich, der ein VARIANT erhält.

    Also auserhalb dieser Funktion!

    Die Eigentliche Frage ist was passiert wenn ich einen VARIANT zurückgebe ist das dann eine Kopie. Was ist der Unterschied wenn ich VariantCopy mache?

    Einfacher ist die Verwendung von CComVariant (oder COleVariant). Die kapseln das für Dich.

    Jo. Das Problem ist dass ich ODK Funktionen von WinCC (Siemens) verwende und deren Schnittstelle ist nun mal VARIANT sonst hätte ich diesen Datentyp gar nicht verwendet.

    Solchen Code halte ich für nicht gut.

    Hier wiederum das Problem dass ich einen CString erhalte und diesen muss ich an die Schnittstelle als VARIANT weiterleiten.

    Bitte verwende Codetags.

    Sorry. Klar mache ich (fast) immer. Hatte es zuspät bemerkt.



  • Oh.

    Wenn Du schon klar einen VT_BSTR zuweist, dann solltest Du auch VT_BSTR direkt setzen. Und höchstens vorher noch einen ASSERT Test machen.

    Jetzt habe ich das erst verstanden! m_varianttype ist immer VT_BSTR.

    Dachte du meinst ich soll keinen CString verwenden. Habe nicht genau gelesen sorry.



  • Nochmals kurz zu dem Rückgabewert VARIANT

    Wenn nun der VARIANT nun ein Member meiner Klasse ist und ich gebe diesen als Kopie zurück muss ich dann VariantClear ausserhalb aufrufen und auch VariantClear im Destruktor meiner Klasse.

    Wie verhält sich das ganze wenn ich eine konstante Referenz des VARIANTS zurückgebe?



  • Da VARIANT keinen eigenen Destruktor hat, musst Du jeden VARIANT genau einmal via VariantClear zerstören, damit seine Ressourcen freigegeben werden.
    Immer vorausgesetzt, er belegt überhaupt welche, siehe vorherige Posts.
    Wenn Du einen VARIANT durch einfache Zuweisung oder Rückgabe aus einer Funktion, wie der TE, erhalten hast, darfst Du den maximal einmal zerstören, weil keine tiefe Kopie erstellt worden ist.
    Wenn Du einen mit VariantCopy kopiert hast, hast Du eine tiefe Kopie erstellt, und musst zu gegebener Zeit beide, Quelle und Ziel, zerstören.



  • Und bei Rückgabe als Referenz verhält es sich wie mit einer Kopie



  • Was muss ich machen dass VariantClear nicht zum Absturz meines Programmes führt.

    Gibts da ne Überprüfung "Variant bereits gelöscht?", oder kann ich eine Exception abfangen?


  • Mod

    VariantCLear führt dann zum Absturz, wenn Du einen Speicher zum Beispiel zweimal freigibst.

    VARIANT var1, var2;
    var1.vt = VT_BSTR;
    var1.bstrVal = anystr.AllocSysString();
    var2 = var1;
    VariantClear(&var1);
    // Crash!
    VariantClear(&var2);
    

    Ist doch logisch.

    Arbeite mit CComVariant und Du hast die Probleme nicht.

    Und solche Exceptions kann man nicht abfangen und sie dann vor allem korrekt behandeln...

    Selbst wenn andere ein VARIANT verwenden, so doch eher VARIANT*! Und hier ist die Behandlung transparent... und selbst wenn nicht. Kannst Du ja jederzeit aus einem CComVariant eine Kopie erzeugen.!


Anmelden zum Antworten