Lorsque je lisais le code source de Seastar , j'ai remarqué qu'il existe une structure d'union appelée tx_side
qui n'a qu'un seul membre. Est-ce un hack pour résoudre un certain problème?
Pour info, je colle la tx_side
structure ci-dessous:
union tx_side {
tx_side() {}
~tx_side() {}
void init() { new (&a) aa; }
struct aa {
std::deque<work_item*> pending_fifo;
} a;
} _tx;
union
au lieu destruct
est une ou plusieurs des différences entre les deux. C'est une technique assez obscure, donc à moins que l'auteur original de ce code ne vienne, je ne suis pas sûr que quelqu'un puisse vous donner une réponse faisant autorité quel problème il espère résoudre avec cela (le cas échéant).Réponses:
Parce que
tx_side
est une union,tx_side()
n'initialise / construit pas automatiquementa
et~tx_side()
ne la détruit pas automatiquement. Cela permet un contrôle fin sur la durée de viea
etpending_fifo
, via le placement, de nouveaux appels de destructeur manuels (ceux d'un pauvrestd::optional
).Voici un exemple:
Ici,
B b;
n'imprime rien, cara
n'est ni construit ni détruit.Si
B
était unstruct
,B()
appelleraitA()
et~B()
appellerait~A()
, et vous ne pourriez pas empêcher cela.la source
int
vous pouvez obtenir0xCCCCCCCC
. La lecture de données non initialisées est un comportement indéfini, et ce qui peut arriver, c'est que le compilateur rejette simplement la tentative. Ce n'est pas seulement de la théorie. Debian a fait cette erreur exacte et a cassé leur implémentation d'OpenSSL. Ils avaient de vrais octets aléatoires, ont ajouté une variable non initialisée, et le compilateur a dit "eh bien le résultat n'est pas défini, donc il pourrait aussi bien être zéro". Zéro n'est évidemment plus aléatoire.!= 0
comparaison ultérieure a donné la valeur true. J'ai depuis ajouté des indicateurs de compilateur pour traiter les variables non initialisées comme des erreurs afin de m'assurer de ne plus tomber dans ce piège.En termes simples, sauf si une valeur explicitement assignée / initialisée, l' union à membre unique n'initialise pas la mémoire allouée. Cette fonctionnalité peut être obtenue avec
std:: optional
en c ++ 17.la source