Die Liste der Änderungen in D 2.092. Ausleihen Ausleihen

Vom Übersetzer. Normalerweise übersetze ich solche Artikel nicht, weil ich darin nichts Interessantes sehe. Hier zwei kleine, aber wichtige Neuerungen - Unterstützung für die direkte Verknüpfung von C ++ - Bibliotheken und das „geliehene“ System des Eigentums und der Ausleihe von Rust (die zweite DFA-Schwalbe, die erste kam erst vor ein paar Tagen in GCC10 heraus, und Nim denkt auch so darüber nach) mit einer Beschreibung. Eigentlich habe ich keine langwierigen Listen übersetzt und die Links führen zum Original.

Vorherige Version der Liste 2.0.91.1 (deu)
Wo man

2.092.0 herunterladen kann, gab es 15 wichtige Änderungen und 44 Fehlerbehebungen und Verbesserungen. Vielen Dank an die 47 Mitwirkenden , die diese Veröffentlichung ermöglicht haben.

Compiler ändert sich


  1. Die Befehlszeilenschalter -revert = import und -transition = checkimports wurden entfernt
  2. Unterstützung für das Codieren (Mangeln) von C ++ GNU ABI-Namen hinzugefügt
  3. Konstruktoren und Destruktoren für Module, die nicht extern sind (D), sind als veraltet markiert
  4. DIP25-Verstöße, die standardmäßig veraltet sind
  5. Prototyp-Besitz- und Ausleihsystem für Zeiger
  6. Hinzugefügt -preview = in - Option , die die Speicherklasse verwandelt sich in in Umfang const
  7. Die Parameter printf und scanf werden jetzt auf Übereinstimmung mit den Formatspezifizierern überprüft
  8. Die Umgebungsvariable SOURCE_DATE_EPOCH wird jetzt unterstützt.

Laufzeitänderungen


  1. TypeInfo_Class/TypeInfo_Interface.isBaseOf C#/Java isAssignableFrom
  2. core.memory.pageSize minimumPageSize


  1. Date.isoWeekYear Date.fromISOWeek std.datetime.date
  2. std.xml
  3. std.digest.digest

Dub


  1. Dub lint --report-file

Die vollständige Liste der Korrekturen und Verbesserungen (Englisch)

Prim.per.U zeigt mir, dass es unmöglich ist, den korrekten Inhalt der In-Page-Links zur Offenlegung wie im Original einzurichten. Sorry = (

Compiler ändert sich


  1. Die Befehlszeilenschalter -revert = import und -transition = checkimports wurden gelöscht.

    Diese Schlüssel haben nichts getan und waren für einige Zeit als veraltet markiert. Der Compiler erkennt sie nicht mehr.
  2. () C++ GNU ABI

    GNU ABI C++11 GCC 5.1. D C++, DMD UDA ( ) gnuAbiTag, core.attribute object ( ). ABI , , ++ . , std::string C++11 (DMD -extern-std={c++11,c++14,c++17}).

    :

    extern(C++):
    @gnuAbiTag("tagOnStruct")
    struct MyStruct {}
    @gnuAbiTag("Multiple", "Tags", "On", "Function")
    MyStruct func();

    gnuAbiTag. ( ). UDA -extern-std=c++11. (-extern-std=c++98) UDA . UDA extern(C++) .
  3. , extern(D) .

    ( ) , extern(D), . , , / , , 479, 479, .

    , , .
  4. DIP25 .

    DIP25 2.067.0, , -preview=dip25. , , DIP1000.

    , , -preview=dip25, -preview=dip25. ( ).

    DIP25 , @ safe . , ref , return , .

    struct Foo
    {
        int x;
        // returning `this.x` escapes a reference to parameter `this`, perhaps annotate with `return`
        ref int method() /* return */ { return this.x; }
    }
    // returning `v` escapes a reference to parameter `v`, perhaps annotate with `return`
    ref int identity(/* return */ ref int v) { return v; }

    return . DIP25 .
  5. -preview=in in scope const.

    const scope, in . , in (. inout ) .

    -preview=in, :

    void fun(in int x);
    void fun(const int x);

    -preview=in, :

    void fun(in int x);
    void fun(scope const int x);
  6. printf scanf

    C99 7.19.6.1 printf 7.19.6.2 scanf.

    printf , . , .

    scanf .

    :

    1. ,
    2. ,
    3. — , s
    4. C99

    -, .

    .

    , printf/scanf, :

    printf("%k\n", value);  // error: non-Standard format k
    const format = "%k\n";
    printf(format.ptr, value);  // no error

    — . ,

    string s;
    printf("%.*s\n", s.length, s.ptr);
    printf("%d\n", s.sizeof);
    ulong u;
    scanf("%lld%*c\n", &u);

    :

    string s;
    printf("%.*s\n", cast(int) s.length, s.ptr);
    printf("%zd\n", s.sizeof);
    ulong u;
    scanf("%llu%*c\n", &u);

    printf scanf pragma(printf) printf pragma(scanf) scanf.

    , :

    1. extern (C ) extern (C++)
    2. const(char)*
    3. … -v , va_list ( «v» printf scanf)
    .

    «v»- .
  7. SOURCE_DATE_EPOCH

    SOURCE_DATE_EPOCH. UNIX ( 1970-01-01 00:00:00), . DMD __DATE__, __TIME__ __TIMESTAMP__ .



Das Besitz- / Ausleihsystem (auch als OB bezeichnet) für Zeiger stellt sicher, dass dereferenzierte Zeiger auf ein gültiges Speicherobjekt verweisen.

Umfang des Prototyp-OB-Systems


Dies ist ein Prototyp des OB-Systems, angepasst für D. Anfangs ist er nur für Zeiger gedacht und nicht für dynamische Arrays, Klassenreferenzen, Referenzen oder Zeigerfelder in Aggregaten. Das Hinzufügen einer solchen Unterstützung erschwert die Implementierung, ändert jedoch nichts an ihrem Wesen, weshalb sie auf später verschoben wird. RAII-Objekte können ihren eigenen Speicher sicher verwalten, sodass sie nicht von OB abgedeckt werden. Unabhängig von der Methode, ob der Zeiger Speicher mithilfe von GC oder einem anderen Allokator zuweist, ist dies für OB nicht wichtig, sie unterscheiden sich nicht und werden identisch verarbeitet.

Das OB-System ist nur in Funktionen aktiv, die mit dem Attribut @ live versehen sind. Sie wird nach der semantischen Verarbeitung ausschließlich zur Überprüfung auf Verstöße gegen die Regeln für organische Substanzen angewendet. Neue Syntax wird nicht hinzugefügt. Am generierten Code werden keine Änderungen vorgenommen. Wenn @ live- Funktionen andere Funktionen als @ live aufrufen , wird erwartet, dass diese aufgerufenen Funktionen eine @ live- kompatible Schnittstelle sind, obwohl sie nicht getestet werden. Wenn nicht @ Live - Funktionen aufrufen @ Live - Funktionen , übergeben die Argumente sollen folgen @ Live - Konventionen .

Das OB-System erkennt Fehler:

  • Dereferenzieren von Zeigern, die sich in einem ungültigen Zustand befinden
  • mehr als ein aktiver Zeiger auf ein mutiertes Speicherobjekt.

Es werden keine Versuche erkannt, einen Nullzeiger oder möglicherweise einen Nullzeiger zu dereferenzieren. Dies funktioniert nicht, da es derzeit keine Methode zum Annotieren eines Typs als nicht nullbaren Zeiger gibt.

Das Grundprinzip von OB


Das OB-Design folgt aus dem folgenden Prinzip:

Für jedes Speicherobjekt kann genau ein mutierender Zeiger darauf oder mehrere nicht mutierende (schreibgeschützte) Zeiger vorhanden sein.

Design


Ein einzelner mutierender Zeiger wird als "Eigentümer" des Speicherobjekts bezeichnet. Er besitzt transitiv ein Speicherobjekt und alle Objekte im Speicher, auf die von dort aus zugegriffen werden kann (d. H. Der Graph von Objekten). Da es der einzige Zeiger auf dieses Speicherobjekt ist, kann es den Speicher sicher verwalten (seine Form ändern, zuweisen, freigeben und seine Größe ändern), ohne den Boden unter den Füßen anderer Zeiger (mutierend oder nicht mutierend) herauszuschlagen, die sich möglicherweise darauf befinden (Grafik) Speicher) anzeigen.

Wenn es mehrere Zeiger auf ein Diagramm von Speicherobjekten gibt, die schreibgeschützt sind, können sie sicher daraus lesen, ohne sich über plötzliche Änderungen im Diagramm der Objekte im Speicher Gedanken machen zu müssen.

Die restlichen Details der Technologie beziehen sich darauf, wie Zeiger schreibgeschützt und ungültig werden und wie das Kernprinzip von OB ständig beibehalten wird.

Verfolgt Zeiger
nur die Zeiger , die deklariert werden in der @ Live - Funktion wie diese , Funktionsparameter oder lokale Variablen verfolgt . Variablen aus anderen Funktionen werden nicht verfolgt, auch nicht @ live , da die Analyse von Interaktionen mit anderen Funktionen nur von der Signatur dieser Funktion und nicht von ihren Interna abhängt. Parameter, die const sind, werden nicht verfolgt.

Zeigerzustände
Jeder Zeiger befindet sich in einem der folgenden Zustände:

Undefiniert
Der Zeiger befindet sich in einem ungültigen Zustand. Das Dereferenzieren eines solchen Zeigers ist ein Fehler.
Besitzer Der
Besitzer ist der einzige Zeiger auf ein Diagramm von Objekten im Speicher. Normalerweise hat ein Zeiger - Besitzer kein Bereichsattribut . Wenn der Zeiger mit dem Gültigkeitsbereichsattribut mit einem Ausdruck initialisiert wird, der nicht vom verfolgten Zeiger abgeleitet ist, wird er zum Eigentümer.
Wenn der Eigentümerzeiger einem anderen Zeiger zugewiesen ist - dem Eigentümer, wechselt der erste in den undefinierten Zustand.
Geliehen
Ein geliehener Zeiger ist ein Zeiger, der vorübergehend der einzige Zeiger auf ein Diagramm von Speicherobjekten wird. Er geht durch Zuweisung vom Zeiger - dem Eigentümer - in diesen Zustand über, während der Eigentümer in den Zustand des Kreditnehmers übergeht, bis die Verwendung des geliehenen Zeigers abgeschlossen ist.
Ein ausgeliehener Zeiger muss ein Bereichsattribut haben und ein Zeiger auf ein veränderbares Objekt sein.
Schreibgeschützt
Der schreibgeschützte Index wird vom Eigentümer zugewiesen. Solange der schreibgeschützte Zeiger aktiv ist, können von diesem Eigentümer nur noch schreibgeschützte Zeiger zugewiesen werden. Der schreibgeschützte Zeiger muss ein Bereichsattribut haben und darf auch kein Zeiger auf ein veränderbares Objekt sein.

Lebenszeiten

Die Lebensdauer des Indikators "Ausgeliehen" oder "Schreibgeschützt" beginnt ab dem Zeitpunkt der ersten Dereferenzierung (und nicht ab dem Zeitpunkt der Initialisierung oder Zuweisung eines Werts) und endet mit der letzten Dereferenzierung des Werts.

Es ist auch als nicht-lexikalische Lebensdauer bekannt .

Zustandsübergänge für Zeiger

Ein Zeiger ändert seinen Zustand, wenn eine dieser Operationen ausgeführt wird:

  • Es wird Speicher zugewiesen (z. B. eine lokale Variable auf dem Stapel), wodurch der Zeiger in einen undefinierten Zustand versetzt wird
  • Initialisierung (als Zuordnung betrachtet)
  • Zuweisung - Die Quell- und Zielzeiger ändern ihren Status abhängig von ihrem Status sowie von ihren Typen und Speicherklassen
  • out ( ), , .
  • ref , , .
  • , .
  • - ()
  • , , .
  • , ,
  • , ,
  • ,


Als Prototyp gibt es viele Aspekte, die noch nicht berücksichtigt wurden und erst dann auftreten werden, wenn der Prototyp zeigt, dass dies eine praktikable Lösung ist.

Fehler

Erwarten Sie viele Fehler. Bitte melden Sie sie Bugzilla und markieren Sie sie mit dem Schlüsselwort "ob". Es ist nicht erforderlich, andere Einschränkungen zu melden, die hier bereits aufgeführt sind.

Verweise auf Klassen und assoziative Arrays werden nicht verfolgt.
Es wird angenommen, dass sie vom GC kontrolliert werden.

Ausleihen und Lesen von Nicht-Eigentümern

Eigentümer werden auf Lecks überwacht, jedoch nicht auf andere Indikatoren. Kreditnehmer gelten als Eigentümer, wenn sie nicht mit einem Zeiger initialisiert werden.

@live void uhoh()
{
    scope p = malloc();  // p is considered an Owner
    scope const pc = malloc(); // pc is not considered an Owner
} // dangling pointer pc is not detected on exit

Es scheint nicht sinnvoll zu sein, Zeiger wie den Bereich zu markieren. Vielleicht kann dies behoben werden, indem dies als Fehler behandelt wird.

Zeiger werden von verschachtelten Funktionen gelesen / geschrieben.
Nicht verfolgt.

@live void ohno()
{
    auto p = malloc();

    void sneaky() { free(p); }

    sneaky();
    free(p);  // double free not detected
}

Ausnahmeanalyse

geht davon aus, dass keine Ausnahmen ausgelöst werden.

@live void leaky()
{
    auto p = malloc();
    pitcher();  // throws exception, p leaks
    free(p);
}

Eine Lösung besteht darin, scope (exit) zu verwenden :

@live void waterTight()
{
    auto p = malloc();
    scope(exit) free(p);
    pitcher();
}

Verwenden Sie entweder RAII-Objekte oder rufen Sie nur Nothrow-Funktionen auf.

Lazy-Parameter

Nicht berücksichtigt.

Quadratische Komplexität Die

Analyse zeigt die quadratische Komplexität. Versuchen Sie, @ live- Funktionen klein zu halten .

Mischen verschiedener Speichergruppen

Kombinieren verschiedener Speicherpools:

void* xmalloc(size_t);
void xfree(void*);

void* ymalloc(size_t);
void yfree(void*);

auto p = xmalloc(20);
yfree(p);  // should call xfree() instead

nicht erkannt.

Dies kann umgangen werden, indem Pools verwendet werden, die für einen bestimmten Typ spezifisch sind:

U* umalloc();
void ufree(U*);

V* vmalloc();
void vfree(V*);

auto p = umalloc();
vfree(p);  // type mismatch

und möglicherweise implizite Konvertierungen in void * in @ live- Funktionen nicht zulassen .

Argumente einer variadischen Funktion

Argumente für eine variadische Funktion (z. B. printf) gelten als verbraucht. Dies ist zwar sicher, scheint jedoch nicht sehr praktisch zu sein und erfordert wahrscheinlich eine Überprüfung.

Laufzeitänderungen


  1. TypeInfo_Class/TypeInfo_Interface.isBaseOf C#/Java isAssignableFrom.

    TypeInfo_Class.isBaseOf true, , , , . isBaseOf, isAssignableFrom, , opAssign D — . TypeInfo_Interface.isBaseOf , TypeInfo_Class, TypeInfo_Interface.
  2. core.memory.pageSize minimumPageSize.

    pageSize .

    import core.memory : pageSize;
    ubyte[] buffer = new ubyte[pageSize];

    minimumPageSize .

    , . , . pageSize, .

    , , , : ubyte[minimumPageSize].

    import core.memory : minimumPageSize;
    ubyte[minimumPageSize] buffer;



  1. Date.isoWeekYear Date.fromISOWeek std.datetime.date

    ISO 8601 , Date and DateTime.

    ISO , . Date.fromISOWeek(2020, 11, DayOfWeek.mon) Date(2020, 3, 9).

    ISO , () .isoWeekYear Date ISO. , .isoWeekAndYear , .
  2. std.xml .

    std.xml . , , UndeaD. xml dub- dxml.
  3. std.digest.digest .

    2.076.1 . std.digest .

    std.digest.digest 2.101.

Dub


  1. .

    Posix , .dub. dub (, .swap.file.d), . , dub . , dub.

    , .
  2. Dub lint --report-file.

    Dub lint --report-file: dub lint --report-file report.json

All Articles