Interface für generischen Typ


  • Mod

    Tachyon schrieb:

    als auch die Exception als auch die throw-Operatoren und deren Positionen.

    Woher?

    extern "weird" void opaque();
    
    void so_something()
    {
       try
       {
           opaque();
       }
       catch ( foo )
    ...
    

    Hier weiß der Compiler gar nichts.



  • Kleiner Test-Code (getestst auf MSVC 9 und gcc 4.5)

    //a.hpp
    struct A{ };
    
    struct B{ };
    
    void f();
    
    //a.cpp
    void f()
    {
        if((std::rand() % 2) == 0)
        {
            throw A();
        }
        else
        {
            throw B();
        }
    }
    
    //main.cpp
    struct E { virtual ~E(){} };
    
    struct F : E { };
    
    int main()
    {
        std::srand(std::time(0));
        for(std::size_t n = 0; n != 10; ++n)
        {
            try
            {
                f();
            }
            catch(A & e) //geht ohne RTTI
            {
                std::cout << "Was A\n";
            }
            catch(B & e) //geht ohne RTTI
            {
                std::cout << "Was B\n";
            }
        }
        A a;
        std::cout << typeid(a).name() << '\n'; //geht ohne RTTI
        F f;
        E &k = f;
        std::cout << typeid(k).name() << '\n'; //geht NICHT ohne RTTI
    
    }
    


  • camper schrieb:

    Tachyon schrieb:

    als auch die Exception als auch die throw-Operatoren und deren Positionen.

    Woher?

    extern "weird" void opaque();
    
    void so_something()
    {
       try
       {
           opaque();
       }
       catch ( foo )
    ...
    

    Hier weiß der Compiler gar nichts.

    Der Exception-Typ muss beidseitig voll bekannt sein. Der Compiler kann entsprechende Linker-Infos in das Compilat einbauen, über die sich das Regeln lässt.



  • Zeus schrieb:

    Vorsicht! Jetzt kommen die Protype-OOP-Jungs und verhauen dich *gg*

    Ja, das würden sie wahrscheinlich - die machen ja den ganzen Tag nichts anderes als diesen Wahnsinn. Ich sehe ihren Kram etwa so wie Perl, Shell oder PHP - für Kleinkram durchaus brauchbar, aber auch, wenn es möglich ist, größere Projekte darin zu entwickeln, lässt man es besser bleiben. Typen zur Laufzeit zusammenbauen, ha! Auf welche Schnittstellen soll man sich denn da noch verlassen können?

    ccquestions: Ich sehe immer noch keinen plausiblen Grund, die Typverarbeitung in die Laufzeit zu verlegen - du musst ja doch zur Compilezeit wissen, welchen Typ du brauchst, und auch, welche du speichern kannst (um sie nämlich speichern zu können). Du könntest sogar das Interface, das du beschreibst, implementieren, wenn UserSettings sich intern mehrere Maps mit verschiedenen Werttypen vorhält, und es spart Laufzeit, weil weniger Schlüsselwerte durchsucht werden müssen. Wobei ich eigentlich kein Problem mit

    UserSettings.StringOptions["FileName"] = "Meine Testdatei";
    

    sehe.

    Trotzdem halte ich es immer noch für sinnvoller, die Einstellungen gleich zu verarbeiten. Du musst ja nicht nur den Typen von GroupModeActivated zur Compilezeit kennen, sondern auch seinen Namen, jedenfalls, sofern du nicht gerade eine Art Framework-Framework baust.

    Exception-Handling wird übrigens heutzutage üblicherweise so betrieben, dass Programmzustände (ähnlich wie mit setjmp gespeichert, wobei stack unwinding das Ganze etwas komplizierter macht) in Dispatch-Tabellen, wie Tachyon sie benennt, verknüpft werden mit Bereichen des Befehlszählers. Aus diesem lässt sich ziemlich offensichtlich eindeutig bestimmen, was gerade geworfen wird.



  • @seldon
    Du verwechselt zwei unterschiedliche Konzepte im Typensystem.
    - class vs protypen
    - statisch vs dynamisch



  • Achso: Am Besten sagt man, danke ich, dass sich RTTI eigentlich nicht abschalten lässt. Zumindest finde ich nichts im Standard, was das vorsieht. Vielleicht bei Free-Standing-Implementierungen. Daher wird es wohl abhängig von der Implementierung sein, was ohne RTTI geht, und was nicht.



  • seldon schrieb:

    ccquestions: Ich sehe immer noch keinen plausiblen Grund, die Typverarbeitung in die Laufzeit zu verlegen - du musst ja doch zur Compilezeit wissen, welchen Typ du brauchst, und auch, welche du speichern kannst (um sie nämlich speichern zu können).

    Ja. Wenn ich nur eine solche Instanz habe, könnte man das auch ganz konventionell realisieren. Aber wenn ich verschiedene sehr ähnliche aber dennoch nicht ausreichend ähnliche "Informationstabellen" habe, dann müsste ich dann für jede dieser Tabellen eine eigene Klasse bauen, obwohl praktisch gleich.

    seldon schrieb:

    Du könntest sogar das Interface, das du beschreibst, implementieren, wenn UserSettings sich intern mehrere Maps mit verschiedenen Werttypen vorhält, und es spart Laufzeit, weil weniger Schlüsselwerte durchsucht werden müssen. Wobei ich eigentlich kein Problem mit

    UserSettings.StringOptions["FileName"] = "Meine Testdatei";
    

    sehe.

    Meine ursprüngliche Realisierung hat ziemlich genau so ausgesehen, ja. Sie ist aber natürlich um einiges weniger flexibel. Es werden nicht derart viele Schlüsselwerte sein, dass eine Auftrennung einen merklichen Performancegewinn bewirken würde.

    seldon schrieb:

    sofern du nicht gerade eine Art Framework-Framework baust.

    Dies ist tatsächlich der Fall. 🙂 Es handelt sich um ein Framework, das auch durch reine Änderung von xml-Konfigurationsdateien und das dazufügen von solchen stark vom Benutzer wird beeinflusst werden können. Beispielsweise neue xml-Definitionsdatei->Neue im Programm zur Verfügung stehende Objektklasse.



  • Zeus schrieb:

    @seldon
    Du verwechselt zwei unterschiedliche Konzepte im Typensystem.
    - class vs protypen
    - statisch vs dynamisch

    Hmm...okay, belehr mich. Ich hatte das jetzt so im Kopf, dass prototypbasierte Sprachen als Typ im Grunde nur Objekte generell kennen und verfügbare Schnittstellen sich zur Laufzeit daraus ergeben, welcher Prototyp geklont bzw. erweitert wurde. Auf die Weise hat man keine Möglichkeit, von beispielsweise seinen Funktionsparametern bestimmte Interfaces zu verlangen und muss entweder darauf hoffen, dass man da nie etwas Falsches bekommt oder sich mit massenhaft NoSuchMethodErrors (oder wie auch immer das gerade heißen mag) herumschlagen, damit man den Zustand seiner Anwendung nicht korrumpiert (lass so was mal in die Nähe einer Datenbank!). Praktisch impliziert für mein Verständnis ein prototypisches Typsystem auch ein dynamisches.

    Aber wenn ich damit falsch liege - hast du eine Webseite oder so zur Hand, wo ich mein Missverständnis korrigieren kann? Ich will ja nicht ewig dumm bleiben.

    @ccquestions: Hm. Also kann ein Benutzer quasi zur Laufzeit neue Typen dazuladen, die von der Anwendung als Werttypen für die Konfiguration benutzt werden? Ich mal mir da jetzt was mit Plugin-Systemen aus, und mein Instinkt wäre es, bei solchen Typen auf einer gemeinsamen Basisklasse zu beharren, die die Konfigurationskomponente kennt, aber so richtig klar ist mir noch nicht, was du da eigentlich baust. Sieht auch so aus, als würde es den Rahmen des Forums sprengen, also unterwerfe ich mich deiner besseren Kenntnis des Sachverhalts.



  • @Tachyon:
    Um herauszubekommen ob ein Catch-Handler passt, muss geprüft werden ob die Typen kompatibel sind.
    Da es nicht möglich ist, das in allen Fällen zur Compile-Zeit zu machen, muss man es (zumindest in manchen Fällen) zur Laufzeit machen.
    Man benötigt also zur Laufzeit Informationen über die Typen.
    Laufzeit. Runtime.
    Informationen über die Typen. Type Information.

    Runtime Type Information.

    RTTI.

    Nen?



  • Tachyon schrieb:

    camper schrieb:

    Tachyon schrieb:

    als auch die Exception als auch die throw-Operatoren und deren Positionen.

    Woher?

    extern "weird" void opaque();
    
    void so_something()
    {
       try
       {
           opaque();
       }
       catch ( foo )
    ...
    

    Hier weiß der Compiler gar nichts.

    Der Exception-Typ muss beidseitig voll bekannt sein. Der Compiler kann entsprechende Linker-Infos in das Compilat einbauen, über die sich das Regeln lässt.

    Der Exception Typ muss in der TU wo der Catch-Handler definiert ist überhaupt nicht bekannt sein, nur der zu-fangende Typ. Und für den reicht soweit ich weiss auch ne fwd. decl., wenn man bloss (by Reference) fangen will, ohne mit dem gefangenen Objekt dann noch was anzustellen.



  • Der Gedanke hinter der Exception ist eigentlich, dass diese überhaupt nicht auftreten sollte wenn der Programmierer keinen Fehler baut - aber man muss natürlich auf die Eventualität vorbereitet sein.

    Ich denke das ist der falsche Ansatz. Zwischen Exceptions und Programmierfehlern sollte mMn unterschieden werden. Programmierfehler kann man auch schön mit einem assert abfangen, Exceptions sollten hingegen für wirkliche Ausnahmesituationen verwendet werden, also Situationen, deren Auftreten du nicht beeinflussen kannst (Datei kann nicht geöffnet werden, kein Festplattenspeicher mehr, etc).

    My 2 cents.



  • seldon schrieb:

    Auf die Weise hat man keine Möglichkeit, von beispielsweise seinen Funktionsparametern bestimmte Interfaces zu verlangen und muss entweder darauf hoffen, dass man da nie etwas Falsches bekommt oder sich mit massenhaft NoSuchMethodErrors (oder wie auch immer das gerade heißen mag) herumschlagen,
    ...
    Praktisch impliziert für mein Verständnis ein prototypisches Typsystem auch ein dynamisches.

    Das hat nichts mit Protoytpen zu tun. Du kannst zB in python ganz ohne Prototypen ein dynamic typing haben.

    Und das dynamische Typsysteme durchaus auch in der Praxis bei großen Anwendungen funktionieren ist erwiesen.

    Und in der Theorie braucht man für prototyping auch kein dynamisches Typsystem. Siehe zB lisaac.



  • @Tachyon: Du hast ja inzwischen zugegeben, dass der Compiler irgendwelche Metainformationen/Tabellen im Kompilat einbauen muss. Ich habe das auch nie "RTTI" genannt. Aber es ist eine Art von Laufzeittyp-Information. Wenn ich "RTTI" sage, dann beschränke (zumindest) ich mich auf das, was typeid braucht, um zu funktionieren. Die Metainformationen, die die Ausnahmebehandlung benötigt, gehen aber in sehr eine ähnliche Richtung.

    Du kannst ja mal in den "C++ performance"-Report reingucken. Da werden u.a. verschiedene Implementierungsansätze für die Ausnahmebehandlung erklärt.



  • hustbaer schrieb:

    Der Exception Typ muss in der TU wo der Catch-Handler definiert ist überhaupt nicht bekannt sein, nur der zu-fangende Typ. Und für den reicht soweit ich weiss auch ne fwd. decl., wenn man bloss (by Reference) fangen will, ohne mit dem gefangenen Objekt dann noch was anzustellen.

    Laut Standard muss der Typ beidseitig voll bekannt sein.



  • hustbaer schrieb:

    Der Exception Typ muss in der TU wo der Catch-Handler definiert ist überhaupt nicht bekannt sein, nur der zu-fangende Typ.

    👍
    (Man denke mal an throw Derived(...) und catch (ABC const& x) .)

    Tachyon, wenn Du meinst, dass auch der Typ Derived in der TU bekannt sein muss, in der das catch hier steht, dann möchte ich gerne ein Zitat aus dem C++ Standard dafür haben. Das würde mich nämlich sehr stark überraschen.



  • Tachyon schrieb:

    hustbaer schrieb:

    Der Exception Typ muss in der TU wo der Catch-Handler definiert ist überhaupt nicht bekannt sein, nur der zu-fangende Typ. Und für den reicht soweit ich weiss auch ne fwd. decl., wenn man bloss (by Reference) fangen will, ohne mit dem gefangenen Objekt dann noch was anzustellen.

    Laut Standard muss der Typ beidseitig voll bekannt sein.

    Komm Tachyon, das geht noch etwas ungenauer.
    Welcher "der Typ"?



  • Shade Of Mine schrieb:

    seldon schrieb:

    Praktisch impliziert für mein Verständnis ein prototypisches Typsystem auch ein dynamisches.

    Das hat nichts mit Protoytpen zu tun. Du kannst zB in python ganz ohne Prototypen ein dynamic typing haben.

    (...)

    Und in der Theorie braucht man für prototyping auch kein dynamisches Typsystem. Siehe zB lisaac.

    Dass man dynamische Typsysteme ohne Prototyping bauen kann, ist mir auch klar. Umgekehrt hatte ich das bislang nicht gesehen; ich werde mir lisaac mal ansehen müssen.

    Shade Of Mine schrieb:

    Und das dynamische Typsysteme durchaus auch in der Praxis bei großen Anwendungen funktionieren ist erwiesen.

    Das nehm ich dir so ohne Qualifikation nicht ab. Nur, dass etwas für große Systeme eingesetzt wird, heißt nicht, dass es auch dafür geeignet ist - siehe Perl. Und gerade auf Python halte ich keine großen Stücke. "Es sollte nur einen Weg geben, etwas zu tun" - so etwas Dämliches hatte ich vor der python philosophy noch nie gehört.

    Was Exceptions angeht: Ich bin der Ansicht, dass man Exceptions nicht zur Steuerung des erwarteten Flusses eines Programms benutzen sollte, etwa um um innere Schleifen zu verlassen, aber auch, dass man sich nicht auf krasse Ausnahmeerscheinungen wie volle Festplatten beschränken sollte. Falsche Eingabedaten reichen schon aus - im Grunde läuft es auf ein "ich komme hier mit dem, was ich habe, nicht weiter" hinaus.

    Ich vermute, dass die Motivation zur Entwicklung von Exceptions darin bestand, dass die damals herkömmliche Fehlerbehandlungsmethode über Rückgabewerte der Form

    err = do_something();
    if(err) { /* Aufräumen und Fehler behandeln */ }
    err = do_something_else();
    if(err) { /* Aufräumen und Fehler behandeln */ }
    err = do_something_else_still();
    if(err) { /* Aufräumen und Fehler behandeln */ }
    
    /* ... */
    

    furchtbar unhandlich war (und deswegen oft komplett unterlassen wurde). Es ist sogar so weit gekommen, dass

    err = do_something();
    if(err) goto error_1;
    err = do_something_else();
    if(err) goto error_2;
    err = do_something_else_still();
    if(err) goto error_3;
    
    /* ... */
    
    error_3:
    cleanup_stage_3();
    error_2:
    cleanup_stage_2();
    error_1:
    cleanup_stage_1();
    

    in C-Code als vernünftiger Mechanismus gilt, eine Art RAII-Imitation. Derartiges zu vermeiden, ist für mein Verständnis der eigentlich große Vorteil von Exceptions - in Verbindung mit RAII, natürlich; ohne automatisierte Aufräumarbeiten müsste man ja doch in jeder umgebenden Funktion die Exception fangen und von Hand aufräumen, vergleichbar mit dem C-Beispiel oben. Java 7 wird übrigens zu diesem Zweck Disposables einführen, die praktisch RAII nachbauen.

    Gehe ich dagegen davon aus, dass ein Fehlerzustand im Normalbetrieb auftreten kann, beispielsweise, dass ein Server am anderen Ende des Netzwerks gerade nicht erreichbar ist, ist es in der Regel handlicher, die Exceptionwerferei sein zu lassen und Rückgabewerte zu benutzen. Ich denke dabei an Anwendungsfälle der Form

    template<typename T, std::size_t N>
    std::size_t array_size(T(&)[N]) { return N; }
    
    // ...
    
    char const *const servers[] = { "foo.bar.com", "bar.baz.com", "qux.quux.com" };
    
    for(std::size_t i = 0;
        i < array_size(servers) && try_connect(servers[i]) != E_SUCCESS;
        ++i);
    
    if(!connection_established()) {
      throw something;
    }
    


  • seldon schrieb:

    Das nehm ich dir so ohne Qualifikation nicht ab. Nur, dass etwas für große Systeme eingesetzt wird, heißt nicht, dass es auch dafür geeignet ist - siehe Perl. Und gerade auf Python halte ich keine großen Stücke. "Es sollte nur einen Weg geben, etwas zu tun" - so etwas Dämliches hatte ich vor der python philosophy noch nie gehört.

    Das sind allesamt keine Gründe gegen dynamic typing.

    Ein paar Vertreter die sehr weit verbreitet sind:
    Python
    Lisp
    Ruby
    Objective C

    Natürlich kann man jetzt sagen Google ist dumm weil sie für viele ihrer Anwendungen Python verwenden. Oder Apple ist dumm weil sie für so ziemlich alles Objective C nehmen. Und Rails ist sowieso dumm :p

    Aber Fakt ist, dass diese Sprachen in großem Stile erfolgreich verwendet.

    Ob man es jetzt mag oder nicht darf in diese Diskussion keine Rolle spielen.



  • hustbaer schrieb:

    Tachyon schrieb:

    hustbaer schrieb:

    Der Exception Typ muss in der TU wo der Catch-Handler definiert ist überhaupt nicht bekannt sein, nur der zu-fangende Typ. Und für den reicht soweit ich weiss auch ne fwd. decl., wenn man bloss (by Reference) fangen will, ohne mit dem gefangenen Objekt dann noch was anzustellen.

    Laut Standard muss der Typ beidseitig voll bekannt sein.

    Komm Tachyon, das geht noch etwas ungenauer.
    Welcher "der Typ"?

    Der Exception-Typ. Eigentlich sollte das ja wohl klar sein.

    Der Standard zum Thema throw :

    ISO/IEC 14882:2003 15.1 §3 schrieb:

    [...]Except for these restrictions and the restrictions on type matching mentioned in 15.3, the operand of throw is treated exactly as a function argument in a call (5.2.2) or the operand of a return statement.

    Zum Thema Handling (und gleichzeitig die Beschreibung der Typanforderung):

    ISO/IEC 14882:2003 15.3 §1 schrieb:

    The exception-declaration in a handler describes the type(s) of exceptions that can cause that handler to be entered. The exception-declaration shall not denote an incomplete type. The exception-declaration shall not denote a pointer or reference to an incomplete type, other than void* , const void* , volatile void* , or const volatile void* . Types shall not be defined in an exception-declaration.

    Sprich, wenn man nichr gerade einen void- Zeiger wirft, muss der Exception-Typ sowohl beim throw , als auch beim catch vollsätndig bekannt sein.
    Da damit z.B. auch alle potentiellen Basisklassen der Exception-Klasse bekannt sind, sollte es auch ohne RTTI kein Problem sein, den richtigen Handler zu finden.

    Nur mal so eine Idee, wie man es machen könnte:

    //user code
    //some.cpp
    void f()
    {
        try
        {
           bar();
        }
        catch(A & e)
        {
        }
        catch(B & e)
        {
        }
        catch(...)
    };
    
    //entstehender Pseudo-Zwischencode und exportierte Symbole  als Linker-Info
    f()
    {
        bar(some::f::call_info);
        if(callback_invoked)
        {
            jump to handling;
        }
    }
    
    void some::f::exc(A & e)
    {
    }
    
    void some::f::exc(B & e)
    {
    }
    
    void some::f::exc(...)
    {
    }
    
    //anderer user code, u.A. mit
    void bar()
    {
        if(very_bad)
        {
            throw A();
        }
    }
    
    //entstehender Pseudo-Zwischencode und exportierte Symbole als Linker-Info
    
    void bar(caller)
    {
        if(very_bad)
        {
            A a;
            caller::exc(a);
        }
    }
    

    Das wäre so eine sehr primitive Möglichkeit als Pseudocode, wie man es machen könnte. Wie gesagt, das ist eh Implementierungsabhängig, da RTTI eigentlich zum standardisierten Sprachkern gehört. Das es ohne RTTI geht, zeigen unterschiedlcihe Compiler. Wie die das im Deteil machen, weiß ich nicht. Wo RTTI fürs Exceptionhandling aus meiner Sicht tatsächlich zwingend ist, ist das Propagieren von Exceptions über dynamische Bibliotheken hinweg.
    Mal davon ab, konnte C++ schon mit Exceptions umgehen, bevor es RTTI gab.



  • Tachyon schrieb:

    Der Exception-Typ. Eigentlich sollte das ja wohl klar sein.

    Nein, so klar ist das nicht, was Du meinst. Es gibt zum einen den dynamischen Typ eines Ausnahmeobjekts und zum anderen den statischen Typ der Ausnahme-Deklaration eines Ausnahmehandlers. Das sind nicht zwingend dieselben Typen. Ich schätze mal, Du meinst den dynamischen Typ des Ausnahmeobjekts.

    Tachyon schrieb:

    Der Standard zum Thema throw :

    ISO/IEC 14882:2003 15.1 §3 schrieb:

    [...]Except for these restrictions and the restrictions on type matching mentioned in 15.3, the operand of throw is treated exactly as a function argument in a call (5.2.2) or the operand of a return statement.

    Ja und? Ich habe das Gefühl, dass Du hier zuviel reininterpretierst.

    Tachyon schrieb:

    Zum Thema Handling (und gleichzeitig die Beschreibung der Typanforderung):

    ISO/IEC 14882:2003 15.3 §1 schrieb:

    The exception-declaration in a handler describes the type(s) of exceptions that can cause that handler to be entered. The exception-declaration shall not denote an incomplete type. The exception-declaration shall not denote a pointer or reference to an incomplete type, other than void* , const void* , volatile void* , or const volatile void* . Types shall not be defined in an exception-declaration.

    Sprich, wenn man nichr gerade einen void- Zeiger wirft, muss der Exception-Typ sowohl beim throw , als auch beim catch vollsätndig bekannt sein.

    Der dynamische Typ des Ausnahmeobjekts muss in der ÜE, in der die passende catch-clause steht nicht bekannt sein. Das einzige, was gefordert wird, ist, dass der statische Typ der exception-declaration vollständig sein muss bzw, falls es sich um einen Zeiger oder eine Referenz handelt, der statische Typ des referenzierten Objekts vollständig sein muss. Das kann aber natürlich auch eine Basisklasse sein, ohne dass der dynamische Typ in der ÜE bekannt sein muss.

    Tachyon schrieb:

    Da damit z.B. auch alle potentiellen Basisklassen der Exception-Klasse bekannt sind, sollte es auch ohne RTTI kein Problem sein, den richtigen Handler zu finden.

    Kommt drauf an, was Du unter "RTTI" verstehst. Ich würde so oder so "RTTI" nicht mit der Ausnahmebehandlung in Verbindung bringen; denn mit RTTI ist typischerweise nur das gemeint, was nötig ist, damit typeid und dynamic_cast funktionieren. Trotzdem erfordert die Ausnahmebehandlung zusätzliche, vom Compiler generierte, Metainformationen, welche den Typ des Ausnahmeobjekts bescheiben, damit der richtige Handler gefunden und initialisiert werden kann.

    Tachyon schrieb:

    Nur mal so eine Idee, wie man es machen könnte:

    ...
    

    Das wäre so eine sehr primitive Möglichkeit als Pseudocode, wie man es machen könnte.

    Mit dem Pseudo-Code kann ich aber so gar nichts anfangen.

    Tachyon schrieb:

    Wie gesagt, das ist eh Implementierungsabhängig, da RTTI eigentlich zum standardisierten Sprachkern gehört. Das es ohne RTTI geht, zeigen unterschiedlcihe Compiler.

    (für eine bestimmte Definition von "RTTI", ja)

    Tachyon schrieb:

    Wie die das im Deteil machen, weiß ich nicht.

    Willst Du auch nicht wissen, oder? Sonst hättest Du nämlich das hier schon gelesen. Hier mal ein Zitat aus dem Report, wo es auf den Punkt gebracht wird:

    5.4.1 Exception Handling Implementation Issues and Techniques
    [...]
    The EH implementation must provide some run-time typeidentification
    mechanism for finding catch clauses when an exception is thrown.

    Tachyon schrieb:

    Mal davon ab, konnte C++ schon mit Exceptions umgehen, bevor es RTTI gab.

    Das schließt nicht aus, dass ein C++ Compiler schon vor der Einfürhung der "RTTI-Features" eine Art von Laufzeittypinformationen für die Ausnahmebehandlung verwendet hat.

    Noch ein Bonus extra für Dich, Tachyon:

    foo.cpp

    void foo()
    {
      throw 42;
    }
    

    console

    > g++ -c foo.cpp
    > objdump -Ct foo.o
    
    SYMBOL TABLE:
    [  0](sec -2)(fl 0x00)(ty   0)(scl 103) (nx 1) 0x00000000 foo.cpp
    File
    [  2](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 1) 0x00000000 foo()
    AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
    [  4](sec  1)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .text
    AUX scnlen 0x32 nreloc 3 nlnno 0
    [  6](sec  2)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .data
    AUX scnlen 0x0 nreloc 0 nlnno 0
    [  8](sec  3)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .bss
    AUX scnlen 0x0 nreloc 0 nlnno 0
    [ 10](sec  0)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000000 [b]typeinfo for int[/b]
    [ 11](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 __cxa_allocate_exception
    [ 12](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 __cxa_throw
    

Anmelden zum Antworten