A lista de alterações no D 2.092. Empréstimos Empréstimos

Do tradutor. Normalmente não traduto esses artigos, porque não vejo nada de interessante neles. Aqui, duas inovações pequenas, mas mais importantes - suporte para vinculação direta de bibliotecas C ++ e o sistema de propriedade "emprestado" e emprestado da Rust (a segunda andorinha do DFA, a primeira lançada no GCC10 apenas alguns dias atrás, e Nim também pensa assim) com uma descrição. Na verdade, não traduzi nenhuma lista tediosa, e os links levam ao original.

A versão anterior da lista 2.0.91.1 (por)
Onde o download do

2.092.0 foi lançado com 15 alterações importantes e 44 correções e melhorias. Muito obrigado aos 47 colaboradores que tornaram esta versão possível.

Alterações do compilador


  1. As opções de linha de comando -revert = import e -transition = checkimports removidas
  2. Adicionado suporte para codificação (desconfiguração) de nomes C ++ GNU ABI
  3. Construtores e destruidores de módulos que não são externos (D) são marcados como obsoletos
  4. Violações DIP25 marcadas por padrão obsoletas
  5. Propriedade de protótipo e sistema de empréstimos para ponteiros
  6. Adicionado = -preview na opção que transforma a classe de armazenamento em em const escopo
  7. Os parâmetros printf e scanf agora são verificados quanto à conformidade com os especificadores de formato
  8. A variável de ambiente SOURCE_DATE_EPOCH agora é suportada.

Mudanças no tempo de execução


  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

Uma lista completa de correções e melhorias (Port.)

Observação.Tenho patas, portanto, não é possível configurar links corretos dentro da página a partir do índice para divulgar os tópicos no original, desculpe = (

Alterações do compilador


  1. A linha de comando alterna -revert = import e -transition = checkimports foram excluídas.

    Essas chaves não fizeram nada e, por algum tempo, ficaram marcadas como obsoletas. O compilador não os reconhecerá mais.
  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__ .



O sistema de propriedade / empréstimo (também conhecido como OB) para ponteiros garante que os ponteiros sem referência apontem para um objeto de memória válido.

Âmbito do sistema OB do protótipo


Este é um protótipo do sistema OB, adaptado para D. Inicialmente, destina-se apenas a ponteiros, e não a matrizes dinâmicas, referências de classe, referências ou campos de ponteiros em agregados. A adição de suporte desse tipo complicará a implementação, mas não muda sua essência; portanto, é adiada para mais tarde. Os objetos RAII podem gerenciar com segurança sua própria memória, para que não sejam cobertos pelo OB. Independentemente do método, se o ponteiro aloca memória usando GC ou algum outro alocador, isso não é importante para o OB, eles não diferem e são processados ​​de forma idêntica.

O sistema OB está ativo apenas em funções anotadas com o atributo @ live. É aplicado após o processamento semântico apenas como verificação de violação das regras de substâncias orgânicas. Nova sintaxe não é adicionada. Nenhuma alteração é feita no código gerado. Se as funções @ live chamarem outras funções que não @ live , é esperado que essas funções chamadas sejam uma interface compatível com @ live , embora não tenha sido testada. Se funções não @ live chamam @ funções live , os argumentos passados ​​devem seguir as convenções @ live .

O sistema OB detecta erros:

  • referenciando ponteiros que estão em um estado inválido
  • mais de um ponteiro ativo para um objeto de memória mutado.

Ele não detectará tentativas de desreferenciar um ponteiro nulo ou, potencialmente, um ponteiro nulo. Isso não funciona, pois atualmente não há método para anotar um tipo como um ponteiro não nulo.

O princípio básico da OB


O design da OB segue o seguinte princípio:

Para cada objeto de memória, pode existir exatamente um ponteiro mutante para ele ou vários ponteiros não mutantes (somente leitura).

Projeto


Um único ponteiro mutante é chamado de "proprietário" do objeto de memória. Ele possui um objeto de memória em trânsito e todos os objetos na memória acessíveis a partir dele (ou seja, o gráfico de objetos). Como é o único ponteiro para esse objeto de memória, ele pode gerenciar com segurança a memória (alterar sua forma, alocar, liberar e redimensionar) sem derrubar o solo sob os pés de quaisquer outros ponteiros (mutantes ou não) que possam estar nele (gráfico memória) indicam.

Se houver vários ponteiros para um gráfico de objetos de memória que sejam somente leitura, eles poderão ler com segurança, sem se preocupar com alterações repentinas no gráfico de objetos na memória.

O restante dos detalhes da tecnologia está relacionado a como os ponteiros se tornam somente leitura e inválidos e como o Princípio Fundamental da OB é mantido constantemente.

Ponteiros
rastreados Apenas os ponteiros declarados na função @ live como esta , parâmetros de função ou variáveis ​​locais são rastreados . Variáveis ​​de outras funções não são rastreadas, mesmo @ live , pois a análise das interações com outras funções depende completamente apenas da assinatura dessa função, e não de seus elementos internos. Parâmetros que são const não são rastreados.

Estados do
ponteiro Cada ponteiro está em um dos seguintes estados:

Indefinido
O ponteiro está em um estado inválido. Desreferenciar esse ponteiro é um erro.
Proprietário O
proprietário é o único ponteiro para um gráfico de objetos na memória. Geralmente um ponteiro - o proprietário não possui um atributo de escopo . Se o ponteiro com o atributo scope for inicializado com uma expressão que não é derivada do ponteiro rastreado, ele se tornará o Proprietário.
Se o ponteiro do proprietário estiver atribuído a outro ponteiro - o proprietário, o primeiro entrará no estado Indefinido.
Emprestado
Um ponteiro emprestado é um ponteiro que temporariamente se torna o único ponteiro para um gráfico de objetos de memória. Ele passa para esse estado através da atribuição do ponteiro - o Proprietário, enquanto o Proprietário passa para o estado do Mutuário até que o uso do ponteiro emprestado seja concluído.
Um ponteiro emprestado deve ter um atributo de escopo e ser um ponteiro para um objeto mutável. Somente
leitura
O índice somente leitura é atribuído pelo proprietário. Enquanto o ponteiro somente leitura estiver ativo, apenas os ponteiros somente leitura ainda poderão ser atribuídos a esse proprietário. O ponteiro somente leitura deve ter um atributo de escopo e também não deve ser um ponteiro para um objeto mutável.

Vida útil

A vida útil do indicador "Emprestado" ou "Somente leitura" começa no momento em que é desferenciada pela primeira vez (e não no momento em que é inicializado ou atribuído um valor) e termina quando o valor é desferenciado pela última vez.

Também é conhecido como Vida Não Lexical .

Transições de estado para ponteiros

Um ponteiro altera seu estado quando uma dessas operações é executada:

  • memória é alocada para ele (por exemplo, uma variável local na pilha), que coloca o ponteiro em um estado indefinido
  • inicialização (considerada como atribuição)
  • atribuição - os ponteiros de origem e destino mudam de estado dependendo de em que estado eles estão, bem como de seus tipos e classes de armazenamento
  • out ( ), , .
  • ref , , .
  • , .
  • - ()
  • , , .
  • , ,
  • , ,
  • ,


Sendo um protótipo, há muitos aspectos que ainda não foram considerados e não serão até que o protótipo mostre que esta é uma solução viável.

Erros

Espere muitos erros. Por favor, reporte-os ao bugzilla e marque com a palavra-chave "ob". Não há necessidade de relatar outras restrições que já estão listadas aqui.

Referências a classes e matrizes associativas não são rastreadas.
Supõe-se que eles sejam controlados pelo GC.

Os empréstimos e as leituras de proprietários não

proprietários são monitorados quanto a vazamentos, mas não outros indicadores. Os mutuários são considerados Proprietários se não forem inicializados com um ponteiro.

@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

Parece que não faz sentido marcar ponteiros como o escopo , talvez isso possa ser corrigido tratando-o como um erro.

Os ponteiros são lidos / gravados por funções aninhadas
.

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

    void sneaky() { free(p); }

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

A

análise de exceções pressupõe que as exceções não são lançadas.

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

Uma solução é usar o escopo (saída) :

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

use objetos RAII ou chame apenas funções de nothrow.

Parâmetros preguiçosos

Não são levados em consideração.

Complexidade quadrática A

análise demonstra a complexidade quadrática, tente manter as funções @ live pequenas.

Misturando grupos de

memória diferentes Combinando conjuntos de memória diferentes:

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

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

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

não detectado.

Isso pode ser contornado usando pools específicos para um tipo específico:

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

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

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

e possivelmente não permitir conversões implícitas para anular * nas funções @ live .

Argumentos de uma função variável Os

argumentos para uma função variável (por exemplo, printf) são considerados consumidos. Embora isso seja seguro, não parece ser muito prático e provavelmente exigirá uma revisão.

Mudanças no tempo de execução


  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