Kiedy czytałem kod źródłowy seastar , zauważyłem, że istnieje zwana struktura związkowa, tx_side
która ma tylko jednego członka. Czy to jakiś hack, aby poradzić sobie z pewnym problemem?
Do Twojej wiadomości wklejam tx_side
poniższą strukturę:
union tx_side {
tx_side() {}
~tx_side() {}
void init() { new (&a) aa; }
struct aa {
std::deque<work_item*> pending_fifo;
} a;
} _tx;
union
zamiaststruct
jednej jest jedna lub więcej różnic między nimi. Jest to dość niejasna technika, więc jeśli nie pojawi się oryginalny autor tego kodu, nie jestem pewien, czy ktoś może udzielić wiarygodnej odpowiedzi na pytanie, jaki problem ma rozwiązać (jeśli w ogóle).Odpowiedzi:
Ponieważ
tx_side
to związek,tx_side()
nie inicjuje / nie konstruuje automatyczniea
i~tx_side()
nie niszczy go automatycznie. Umożliwia to drobiazgową kontrolę nad czasem życia,a
a takżepending_fifo
poprzez nowe połączenia i ręczne wywołania destruktora (biednego człowiekastd::optional
).Oto przykład:
Tutaj
B b;
nic nie drukuje, ponieważa
nie jest konstruowane ani niszczone.Gdyby
B
byłstruct
,B()
zadzwoniłbyA()
i~B()
dzwoniłby~A()
, a ty nie byłbyś w stanie temu zapobiec.źródło
int
, możesz go otrzymać0xCCCCCCCC
. Odczytywanie niezainicjowanych danych jest zachowaniem niezdefiniowanym, a to, co może się zdarzyć, polega na tym, że kompilator po prostu odrzuca próbę. To nie tylko teoria. Debian popełnił właśnie ten błąd i złamał ich implementację OpenSSL. Mieli kilka prawdziwych losowych bajtów, dodali niezainicjowaną zmienną, a kompilator powiedział: „wynik jest niezdefiniowany, więc równie dobrze może wynosić zero”. Zero oczywiście nie jest już przypadkowe.!= 0
porównanie się sprawdziło. Od tego czasu dodałem flagi kompilatora do traktowania niezainicjowanych zmiennych jako błędów, aby upewnić się, że nie wpadnę ponownie w tę pułapkę.Krótko mówiąc, jeśli jednoznacznie nie przypisano / nie zainicjowano wartości, jedno połączenie nie inicjuje przydzielonej pamięci. Funkcjonalność tę można osiągnąć za pomocą
std:: optional
c ++ 17.źródło