Wieso wird nicht initialisiert?



  • dot schrieb:

    Ja es ist unnötig. Wieso ist das wohl so 🙄

    Was soll denn das bedeuten? Dass es intuitiv und auch für Anfänger sofort ersichtlich ist, dass es hier keine Initialisierung braucht?



  • dot schrieb:

    Ja es ist unnötig. Wieso ist das wohl so 🙄

    Sachmal, wenn du nur Augen drehen willst, hättest du dir den Text auch gleich sparen können. Wieso muss immer jemand seine miese Laune an anderen rauslassen?

    @theta, danke gute Antwort.



  • Tante Emma schrieb:

    dot schrieb:

    Ja es ist unnötig. Wieso ist das wohl so 🙄

    Was soll denn das bedeuten? Dass es intuitiv und auch für Anfänger sofort ersichtlich ist, dass es hier keine Initialisierung braucht?

    Das könnte bedeuten, dass man sich auch mal die Mühe machen könnte die Doku zu lesen.



  • cooky451 schrieb:

    Tante Emma schrieb:

    dot schrieb:

    Ja es ist unnötig. Wieso ist das wohl so 🙄

    Was soll denn das bedeuten? Dass es intuitiv und auch für Anfänger sofort ersichtlich ist, dass es hier keine Initialisierung braucht?

    Das könnte bedeuten, dass man sich auch mal die Mühe machen könnte die Doku zu lesen.

    Vielleicht 🙄

    😉



  • [quote="cooky451"]

    Tante Emma schrieb:

    Das könnte bedeuten, dass man sich auch mal die Mühe machen könnte die Doku zu lesen.

    Diese Mühe habe ich mir gemacht. Wieso ein "in" bzw "out" Parameter aber garantiert uninitialisiert sein darf, steht dort jedoch nicht. Was, wenn innerhalb dieser Funktion etwas schief geht, am falschen (0) Wert des Parameters würde man es jedenfalls nicht erkennen können.



  • ob das Initialisieren hier unnötig ist – und wieso?

    Weil Output-Variablen überschrieben werden und ihre Initialwerte (soweit sie nicht als InOut gekennzeichnet sind) nicht verwendet werden.

    Was, wenn innerhalb dieser Funktion etwas schief geht, am falschen (0) Wert des Parameters würde man es jedenfalls nicht erkennen können.

    Dafür gibt's die Funktionsrügabewerte.



  • Weil Output-Variablen überschrieben werden und ihre Initialwerte (soweit sie nicht als InOut gekennzeichnet sind) nicht verwendet werden.

    Und wo wird das so festgeschrieben? Kling ja einleuchtend, deckt sich mit Erfahrungen und ich will auch nicht haarespalten, mich interessiert nur wo man solche "Grundgesetze" findet. Die in/out Bezeichnung im MSDN sind ja nur Hinweise und keine Vorgabe wie der Datentyp, nehme ich an.



  • MSDN schrieb:

    Receives a pointer to the retrieved CLSID on return.



  • mikeem schrieb:

    Und wo wird das so festgeschrieben? Kling ja einleuchtend, deckt sich mit Erfahrungen und ich will auch nicht haarespalten, mich interessiert nur wo man solche "Grundgesetze" findet. Die in/out Bezeichnung im MSDN sind ja nur Hinweise und keine Vorgabe wie der Datentyp, nehme ich an.

    Dazu gibt's keine Grundgesetze. Also na ja, wenn ein const* erwartet wird, wird nicht rein geschrieben, macht also irgendwie nur Sinn, wenn man Werte übergibt. Andersrum kann man sich allerdings nicht darauf verlassen, dass nicht auch gelesen wird. Daher wirst du wohl nicht drum herum kommen die Doku zu lesen. Im MSDN gibt es [in], [in/out] und [out]. Bei [out] wird natürlich nicht gelesen und deshalb sind die Eingangswerte egal.



  • mikeem schrieb:

    Die in/out Bezeichnung im MSDN sind ja nur Hinweise und keine Vorgabe wie der Datentyp, nehme ich an.

    Doch, das sind Vorgaben. Ein bisschen Spielraum ist dir durch [opt] gegeben. An alles andere musst du dich bzw. deinen Code halten, wenn du nicht willst, dass da etwas schief läuft.

    Ich korrigiere: es sind Hinweise auf die Funktionsweise der Methode und damit indirekt Vorgaben.



  • Bei der API aus meinem ersten Beitrag steht das in/out als Randnotiz in der Hilfe (MSDN). Wie kommt man bei einer Hilfe-losen Funktion darauf, dass dieser Parameter uninitialisiert sein darf?
    danke 🙂



  • Ich verstehe dich nicht.

    Parameters

    lpszProgID [in]
    A pointer to the ProgID whose CLSID is requested.

    lpclsid [out]
    Receives a pointer to the retrieved CLSID on return.

    Das ist doch wohl mehr als deutlich?



  • mikeem schrieb:

    Wie kommt man bei einer Hilfe-losen Funktion darauf, dass dieser Parameter uninitialisiert sein darf?
    danke 🙂

    Die Funktion ist nicht "Hilfe-los". In der Dokumentation steht absolut eindeutig wie die Funktion zu benutzen ist.



  • Bei einer Funktion mit out-Parametern, die "schiefgehen" könnte, kannst du davon ausgehen, dass einer der folgenden Punkte der Fall ist:

    a) Wenns schiefgeht steht im out-Parameter ein Wert, der anzeigt, dass es schiefgegangen ist. Das sollte dokumentiert sein.
    b) Es gibt einen Rückgabewert oder einen anderen out-Parameter, der anzeigt, dass mit der Funktion was schiefgelaufen ist, und dass man sich auf den out-Parameter, um den es geht, nicht verlassen darf. Das sollte dokumentiert sein.
    c) Der Hersteller der Bibliothek hat wenig Ahnung und ein Stück Code geschaffen, bei dem man sich auf das Resultat im out-Parameter so oder so nicht verlassen kann, weil man keine Möglichkeit hat, festzustellen, ob etwas "schiefgegangen" ist oder nicht. Natürlich ist das dann auch nicht dokumentiert.

    Im letzten Fall bringt leider auch eine vorherige Initialisierung nichts, weil du nicht sicher sein kannst, ob in der Funktion vor dem "schiefgehen" nicht schon irgendwas in den out-Parameter geschrieben wurde. Wenn du den Hersteller bzw. die Funktion verdächtigst, zu Kategorie c) zu gehören, gibt es nur eine Möglichkeit, ein verlässliches Programm zu schreiben: Andere Bibliothek und andere Funktion benutzen.



  • Die "__out" Teile sind Attribute, die der MSVC verwenden kann um Static-Code-Analysis zu machen. Ich würde sie als "100% verpflichtend" ansehen.

    @pumuckl:
    Ja, da fehlt wohl noch ein Konsens in der C++ Community.

    COM z.B. schreibt einigermassen gut vor wie mit [out] Parametern umzugehen ist.
    Die Aufrufende Funktion sollte den Wert ignorieren, wenn die Funktion einen Fehler zurückgegeben hat.
    Und die Funktion selbst ist verpflichtet [out] Parameter auf einen Wert zu setzen, der
    a) unproblematisch als "initialisiert" behandelt werden kann und gleichzeitig
    b) kein "cleanup" erfordert
    wenn sie einen Fehler zurückgibt.
    Also z.B. 0 für BSTR, Interface-Zeiger oder dergleichen.

    D.h. das wäre z.B. nicht OK:

    HRESULT Fun([out] IUnknown** p1, [out] IUnknown** p2)
    {
        if (p1)
            *p1 = 0;
        else
            return E_POINTER; // mööp, p2 könnte non-NULL sein, wurde aber nicht auf einen "unproblematischen" Wert gesetzt
    
        if (p2)
            *p2 = 0;
        else
            return E_POINTER;
    
        // ....
        return S_OK;
    }
    

    Korrekt müsste man es so machen:

    HRESULT Fun([out] IUnknown** p1, [out] IUnknown** p2)
    {
        if (p1)
            *p1 = 0;
        if (p2)
            *p2 = 0;
    
        if (!p1 || !p2)
             return E_POINTER;
    
        // ....
        return S_OK;
    }
    

Anmelden zum Antworten