Possono esserci diversi oggetti impliciti basati su una decisione di runtime successiva in C ++ 20?


11

Questa domanda si riferisce all'aggiunta di P0593 al più recente C 20 progetti ++ .

Ecco il mio esempio:

#include <cstdlib>
#include <cstdio>

void foo(void *p)
{
    if ( std::getchar() == 'i' )
    {
        *(int *)p = 2;
        std::printf("%d\n", *(int *)p);
    }
    else
    {
        *(float *)p = 2;
        std::printf("%f\n", *(float *)p);
    }
}

int main()
{
    void *a = std::malloc( sizeof(int) + sizeof(float) );
    if ( !a ) return EXIT_FAILURE;

    foo(a);
    // foo(a);    [2]
}

Questo codice è ben definito per tutti gli input nell'ultima bozza?

La logica espressa in P0593 chiarisce abbastanza chiaramente che il non commento [2]porterebbe a comportamenti indefiniti a causa di una severa violazione dell'aliasing, se i due elementi di input dell'utente differiscono. La creazione implicita di oggetti dovrebbe avvenire solo una volta, al punto di malloc; non è attivato dall'istruzione di assegnazione in foo.

Per qualsiasi esecuzione effettiva del programma, esiste un membro dell'insieme non specificato di oggetti impliciti che renderebbe il programma ben definito. Ma non mi è chiaro se la scelta della creazione implicita di oggetti menzionata in [intro.object] / 10 debba essere fatta quando ciò mallocaccade; o se la decisione può "viaggiare nel tempo".

Lo stesso problema può sorgere per un programma che legge un BLOB binario in un buffer e quindi prende una decisione di runtime su come accedervi (ad es. Deserializzazione; e l'intestazione ci dice se sta arrivando un float o un int).

Risposte:


9

La creazione implicita di oggetti dovrebbe avvenire solo una volta, al punto di malloc; non è attivato dall'istruzione di assegnazione in foo.

Questo non è rilevante. Ciò che conta è quale oggetto viene creato. Lo standard dice che l'oggetto che viene creato è uno che trasforma qualcosa che sarebbe stato UB in un codice ben definito:

tale operazione crea e avvia implicitamente la durata di zero o più oggetti di tipi di durata implicita ([basic.types]) nella regione di archiviazione specificata se ciò comporterebbe che il programma abbia un comportamento definito.

Il comportamento si basa in definitiva sull'esecuzione del runtime, non sull'analisi statica. Quindi devi solo seguire l'esecuzione del programma fino a quando non ti imbatti in un caso in cui il comportamento non sarebbe definito, ma sarebbe definito se un oggetto di qualche tipo fosse stato creato in quella memoria al momento dell'operazione in questione.

Quindi la posizione della creazione è sempre "l'operazione", ma la determinazione di ciò che viene creato si basa sul modo in cui la memoria viene utilizzata in fase di esecuzione (ovvero: comportamento).


2
Per essere chiari, stai dicendo che il mio codice è ben definito?
MM

2
@MM: è corretto.
Nicol Bolas,
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.