void reference?



  • @Shade
    Hier gibt es kein Undefiniertes Verhalten. Das Programm stürzt immer ab, es sei denn man kann den Zugriff auf NULL-Speicher abfangen (kann ich im Moment net sagen ob und wie's geht).

    Ich weiss nicht, ob einige Leute den Code mal durch nen Debugger gejagt haben. Mir kommts so vor als ob das einige mal tun sollten. Vielleicht ist da ja auch jeder Compiler anders gepolt. Beim MSC jedenfalls ergibt sich das Verhalten so wie ich es erklärt habe und das ist für mich logisch.

    template <class T>
    T& invalid_ref(T* x)
    {
        T* tmp = NULL;
        return *tmp; // hier wird nicht NULL dereferenziert, sondern tmp
                     // und tmp ist eine gültige Variable mit gültigem Speicher
                     // dass tmp ein Zeiger ist, der auf NULL zeigt -> geschenkt
                     // letztendlich wird zwar ein NULL Objekt zurückgegeben,
                     // interessiert hier aber nicht, da ich weder lesend noch
                     // schreibend zugreife
    }
    
    int main()
    {
        int a = 1;
        int& b = invalid_ref(&a);
        b = 2;    // erst hier machts oops, weil ich jetzt auf ein NULL-Objekt
                  // schreibend zugreife
    }
    


  • groovemaster2002 schrieb:

    @Shade
    Hier gibt es kein Undefiniertes Verhalten. Das Programm stürzt immer ab, es sei denn man kann den Zugriff auf NULL-Speicher abfangen (kann ich im Moment net sagen ob und wie's geht).

    ... oder man hat ein System ohne Speicherschutz (MS-DOS, alte MacOS-Versionen etc.). Ich weiß nicht, was du unter undefiniertem Verhalten verstehst. Wir verwenden hier jedenfalls die Bedeutung aus dem C++-Standard, und nach der bedeutet das schlicht und einfach, dass der Standard keinerlei Forderungen an den Effekt stellt. Ein Absturz ist genauso zulässig wie irgendwas anderes, egal was.



  • groovemaster2002 schrieb:

    template <class T>
    T& invalid_ref(T* x)
    {
        T* tmp = NULL;
        return *tmp; // hier wird nicht NULL dereferenziert, sondern tmp
                     // und tmp ist eine gültige Variable mit gültigem Speicher
                     // dass tmp ein Zeiger ist, der auf NULL zeigt -> geschenkt
                     // letztendlich wird zwar ein NULL Objekt zurückgegeben,
                     // interessiert hier aber nicht, da ich weder lesend noch
                     // schreibend zugreife
    }
    
    int main()
    {
        int a = 1;
        int& b = invalid_ref(&a);
        b = 2;    // erst hier machts oops, weil ich jetzt auf ein NULL-Objekt
                  // schreibend zugreife
    }
    

    vielleicht solltest du nicht den debugger bemühen, sondern ein gutes Buch?

    Der Grund warum er dort oben nicht abschmiert ist wahrscheinlich der, dass Referenzen intern als Zeiger gehandhabt werden und keine Dereferenzierung stattfindet.

    Das ist aber Implementierungsabhängig...



  • per definitionem erzeugt das dereferenzieren eines zeigers, der auf NULL zeigt, undefiniertes verhalten - so der standard.
    und undefiniertes verhalten heißt, wie der name schon sagt, es kann geschehen, was geschehen will.



  • Der Compiler könnte die Dereferenzierung allerdings wegoptimieren, wenn er sieht, dass der Zeiger dereferenziert und dann direkt an die Referenz übergeben wird, das könnte ich mir auch vorstellen.



  • Der Standard erwähnt sogar ausdrücklich, dass in einem legalen Programm Referenzen auf Null nicht vorkommen können - weil man sie eben nur erzeugen kann, wenn man einen Nullzeiger dereferenziert (8.3.2)
    Egal ob der Compiler etwas wegoptimieren kann oder nicht - Wenn es so im Code steht, dann ist es einfach undefiniert, was herauskommt.



  • Ich habe beim MSVC sogar schon ne Referenz angelegt, die ich nicht
    initialisiert habe und erst spaeter auf eine Variable habe referenzieren
    lassen 😃

    Sollte er das eigentlich nicht _nicht_ schlucken? 🙄

    Soviel zum manchmal komischen Verhalten vom MSVC 😉

    mfg
    v R



  • Da würde mich ja interessieren, wie du das gemacht hast.



  • Bashar schrieb:

    Da würde mich ja interessieren, wie du das gemacht hast.

    Na das weisst du doch, war doch damals mit dir im chat und hatte den Code auch
    irgendwo auf rafb gepostet gehabt...mal sehn ob ich den wiederfinde. Weiss noch,
    dass der Borland-Compiler und der gcc den Code nicht geschluckt hat.

    War glaub ich sowas in der Art:

    int &i;
    
    int j;
    
    i = j;
    

    Ich schau nochmal nach, ansonsten kann ich ja nochmal MSVC installieren und
    das ganze nochmal machen.

    Wenn jemand das Visual Studio.net 2002 hat, sollte er das Ganze nachvollziehen
    koennen.

    mfg
    v R



  • davie schrieb:

    Der Standard erwähnt sogar ausdrücklich, dass in einem legalen Programm Referenzen auf Null nicht vorkommen können - weil man sie eben nur erzeugen kann, wenn man einen Nullzeiger dereferenziert (8.3.2)

    Der Standard spricht nicht von legalen, sondern von "well-defined
    program". Und genau mit dieser Aussage bestätigst du, dass sich der Code so verhält, wie ers tut.

    T* tmp = NULL;
        return *tmp;
    

    Hier passiert nix undefiniertes. Es wird laut Standard eine null reference "erzeugt". Was damit passiert ist undefiniert (geb ja zu, dass dies nicht immer zu einem Absturz führen muss - auch wenn das auf x86 Plattformen die Regel sein wird). Mich störte nur, dass Shade schrieb:

    b = 2;    // oops :-o //nein, hier kein oops
    

    Wenn das Programm nicht irgendwo nach dem return sich undefiniert verhält, hier tut es das auf jeden Fall. Mir geht es aber nicht darum zu streiten, wo's oopst, sondern dass man die "sicheren" Referenzen auch missbrauchen kann.



  • groovemaster2002 schrieb:

    Hier passiert nix undefiniertes.

    Soll ich dir den Standard vorlesen?

    hier mal ganz langsam zum mitschreiben:

    in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the "object" obtained by dereferencing a null pointer, which causes undefined behavior.

    Was ist daran unverständlich?
    Wenn dir "well-defined" nicht gefällt, siehe 1.3.* - dort gibts n paar Erklärungen die du dir mal reinziehen solltest.



  • Sicherlich kann man den Satz unterschiedlich interpretieren, ich lese da 2 Fakten raus:
    1. das Dereferenzieren eines Null-Zeigers ergibt immer eine Null-Referenz - da is nix undefiniert dran
    2. die Auswirkungen durch die Benutzung einer Null-Referenz sind dagegen undefined, weshalb man sie in einem "well-defined" Programm nicht benutzen soll.



  • du interpretierst ihn aber falsch.



  • mit der zeile

    return *tmp;
    

    dereferenzierst du einen nullzeiger, zumindest darüber sind wir uns einig?



  • @groovemaster:

    A macht was kaputt, so daß B nicht mehr funktioniert. Wo gehört jetzt das Oops hin? Da wo A was kaputt macht (meine Meinung) oder da wo jemand ahnungsloses versucht B trotzdem zu benutzen?



  • oline schrieb:

    du interpretierst ihn aber falsch.

    Wieso tust du mir nicht den Gefallen und begründest deinen Standpunkt.

    davie schrieb:

    dereferenzierst du einen nullzeiger, zumindest darüber sind wir uns einig?

    Absolut. Null-Zeiger und nicht NULL, wie einige schrieben.
    Und was entsteht laut Standard, wenn man dies tut? Darüber sind wir uns doch auch einig?



  • genau, undefiniertes verhalten.
    damit ist alles, was später passiert egal.



  • groovemaster2002 schrieb:

    1. das Dereferenzieren eines Null-Zeigers ergibt immer eine Null-Referenz - da is nix undefiniert dran

    Dann lies mal
    "a null reference cannot exist in a well-defined program"

    Was kann man daran falsch verstehen?

    Weiters siehe 1.9p4

    Certain operations are described in this International Standard as undefined (for example dereferencing the null pointer)

    Das sind Sachen die man einfach nicht anders interpretieren kann.

    btw: well-defined heisst: Programm mit definiertem verhalten - dies bedeutet, not well-defined ist ein "kaputtes" Programm



  • @Jester
    Das oops gehört für mich dorthin, wo undefiniertes Verhalten in Erscheinung tritt (ich weiss, dass diese Antwort dich nicht glücklich machen wird 😃 ).

    davie schrieb:

    genau, undefiniertes verhalten.

    Nein, eben nicht. Es entsteht eine Null-Referenz. Punkt. Bis dorthin gibt es noch kein undefiniertes Verhalten. Alles was danach kommt bzw. mit dieser Null-Referenz angestellt wird, ist undefiniert.

    @Shade
    Ich würde ja gern was antworten. Nur kann ich deine Argumente nicht mehr ganz nachvollziehen. Nicht dass sie falsch wären, nur von meinem Standpunkt aus habe ich auch nichts anderes behauptet.



  • groovemaster2002 schrieb:

    davie schrieb:

    genau, undefiniertes verhalten.

    Nein, eben nicht. Es entsteht eine Null-Referenz. Punkt. Bis dorthin gibt es noch kein undefiniertes Verhalten. Alles was danach kommt bzw. mit dieser Null-Referenz angestellt wird, ist undefiniert.

    Erklaer mir bitte, wie du
    "a null reference cannot exist in a well-defined program"
    interpretierst.

    Ich verstehe dies so:
    Eine "NULL Reference" kann es nicht geben - somit bedeutet jedes auftreten einer "NULL Reference" undefiniertes Verhalten. Denn der Standard legt fest, dass es eine "NULL Reference" nicht gibt, deshalb kann er nicht definieren was beim auftreten einer "NULL Reference" passiert, ergo ist es nicht definiert (undefiniert)

    Weiters interpretiere ich
    "Certain operations are described in this International Standard as undefined (for example dereferencing the null pointer)"
    folgendermassen:

    Einige Operationen sind undefiniert, darunter faellt auch das dereferenzieren eines NULL Zeigers.

    char* tmp=NULL;
    dies ist ein NULL Zeiger.

    *tmp;
    dies ist eine Dereferenzierung.

    Da tmp ein NULL Zeiger ist, wird hier also ein NULL Zeiger derefrenziert, was mit undefiniertem Verhalten bestraft wird.

    @Shade
    Ich würde ja gern was antworten. Nur kann ich deine Argumente nicht mehr ganz nachvollziehen. Nicht dass sie falsch wären, nur von meinem Standpunkt aus habe ich auch nichts anderes behauptet.

    Meine Argumente sind Zitate aus dem Standard - mehr nicht.
    Bitte interpretiere fuer mich die von mir zitierten Stellen. Fuer mich ist da eigentlich alles klar.


Anmelden zum Antworten