È UB a riprendere una routine di funzione membro di un oggetto la cui durata è terminata?


9

Questa domanda nasce da questo commento: spiegazione a vita Lambda per coroutine C ++ 20

riguardo a questo esempio:

auto foo() -> folly::coro::Task<int> {
    auto task = []() -> folly::coro::Task<int> {
        co_return 1;
    }();
    return task;
}

Quindi la domanda è se l'esecuzione della coroutine restituita foocomporterebbe UB.

"Chiamare" una funzione membro (al termine della durata dell'oggetto) è UB: http://eel.is/c++draft/basic.life#6.2

... qualsiasi puntatore che rappresenta l'indirizzo della posizione di archiviazione in cui si troverà o si trovava l'oggetto può essere utilizzato, ma solo in modo limitato. [...] Il programma ha un comportamento indefinito se:

[...]

- il puntatore viene utilizzato per accedere a un membro di dati non statico o per chiamare una funzione di membro non statico dell'oggetto , oppure

Tuttavia, in questo esempio:

  • ()viene chiamato l' operatore del lambda mentre la durata del lambda è ancora valida
  • Viene quindi sospeso,
  • allora la lambda viene distrutta,
  • e quindi la funzione membro (operatore ()) viene ripresa in seguito.

Questa ripresa è considerata un comportamento indefinito?


2
Forse la seguente risposta è rilevante stackoverflow.com/a/60495359/12345656 Sembra piuttosto diversa, ma riguarda anche una funzione membro durante la quale l'esecuzione del thispuntatore viene invalidata. Considera anche la discussione nei commenti.
n314159

Risposte:


2

[dcl.fct.def.coroutine] p3 :

Il tipo di promessa di una coroutine è std::coroutine_traits<R, P1, ..., Pn>::promise_type, dov'è Ril tipo di ritorno della funzione, e P1 ... Pnsono la sequenza di tipi dei parametri della funzione, preceduta dal tipo del parametro oggetto implicito (12.4.1) se la coroutine è un non statico funzione membro.

Il parametro oggetto implicito è nel tuo esempio un riferimento const, e quindi tale riferimento sarà penzolante quando l'esecuzione viene ripresa dopo che l'oggetto di chiusura è stato distrutto.

Tuttavia, sulla nota degli oggetti che vengono distrutti durante l'esecuzione di una funzione membro, questo in effetti va bene di per sé, e nientemeno che lo standard stesso implica questo in [basic] :

Prima che la durata di un oggetto sia iniziata, ma dopo che è stata allocata la memoria che l'oggetto occuperà o, al termine della durata di vita di un oggetto e prima che la memoria di cui l'oggetto occupato sia riutilizzato o rilasciato, qualsiasi puntatore che rappresenta l'indirizzo di la posizione di archiviazione in cui si troverà o si trovava l'oggetto può essere utilizzata, ma solo in modo limitato. [...]

void B::mutate() {
  new (this) D2;    // reuses storage --- ends the lifetime of *this
  f();              // undefined behavior
  ... = this;       // OK, this points to valid memory
}

(NB: l'UB sopra riportato è perché l'implicito thisnon è riciclato e fa ancora riferimento al parametro oggetto implicito.)

Quindi il tuo esempio sembra essere ben definito, subordinato all'idea che la ripresa dell'esecuzione non rientri nelle stesse regole di una chiamata originale. Si noti che il riferimento all'oggetto di chiusura potrebbe essere pendente, ma non è possibile accedervi in ​​alcun modo tra sospensione e ripresa.


Intendi "ripresa e completamento" alla fine?
Davis Herring,

@DavisHerring No, intendevo specificatamente entro quel lasso di tempo "esterno", in cui non è chiaro se il riferimento potesse essere assegnato a un nuovo riferimento ecc. Che richiederebbe un oggetto reale. Il fatto che il riferimento non sia accessibile in modo nascosto è importante affinché questo non sia UB
Columbo

Ma non è sufficiente lasciare solo il riferimento penzolante fino alla ripresa; devi lasciarlo solo ( ad esempio , nel corpo lambda) per sempre, per il resto della sua vita, che è fino al completamento. Quindi forse dovrebbe essere "sospensione e completamento".
Davis Herring,

@DavisHerring Ho menzionato specificamente quell'intervallo, perché nel nostro esempio sappiamo che l'altro è sicuro.
Columbo,

Sicuro; Trovo confuso il testo. Forse nessun altro lo fa.
Davis Herring,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.