3 votes

Est-ce que reinterpret_cast provoque une violation stricte de l'aliasing ?

Pourquoi existe-t-il ? Dans quelles situations ne provoque-t-il pas une violation stricte de l'aliasing, et dans lesquelles en provoque-t-il une ?

Je veux dire, si vous effectuez un cast entre deux types incompatibles, et que le résultat de ce cast est le seul pointeur qui pointe vers la mémoire qu'il utilise dans tout le programme, est-il sûr de l'utiliser alors en supposant qu'aucun autre alias ne fait référence à cette mémoire ? Est-il alors sûr de le remettre dans son type original et de l'utiliser en supposant que la variable où il est stocké est le seul alias à cet emplacement de mémoire dans le programme ? C'est ce que je demande.

Par utiliser, j'entends bien sûr lire et écrire.

4voto

user2079303 Points 4916

Est-ce que reinterpret_cast provoque une violation stricte de l'aliasing ?

Pas tout seul, non. Mais sa mauvaise utilisation peut conduire à une telle violation.

Ce n'est pas une bonne idée d'utiliser reinterpret cast à moins que vous ne sachiez que vous en avez besoin (rare), que vous sachiez qu'il n'y a pas d'alternative satisfaisante (plus rare), et que vous sachiez que cela n'entraînera pas un comportement indéfini.

pourquoi existe-t-il ?

Comme son nom l'indique, pour permettre la réinterprétation des types. Les cas d'utilisation sont rares en C++ et ne sont pas destinés aux programmeurs débutants, ni intermédiaires.

Quelques cas où un programmeur avancé pourrait le trouver utile :

  • Sérialisation
  • Les interfaces C qui utilisent la réinterprétation comme une forme de polymorphisme.

Dans quelles situations ne provoque-t-il pas de violation stricte du crénelage, et dans quelles situations en provoque-t-il une ?

La distribution elle-même ne provoque jamais d'infraction.

Les violations de l'aliasing strict ne peuvent se produire que lorsque vous avez effectué un casting vers un pointeur (ou une référence) d'un autre type, et ensuite indirectement par ce pointeur et accéder à l'objet. Ainsi, si vous ne réinterprétez pas le cast d'un pointeur (ou d'une référence), ou si vous n'accédez pas à l'objet pointé, alors vous n'aliassez pas le type de l'objet, et ne pouvez donc pas violer les règles strictes d'aliasing.

Ce qui est intéressant, c'est de savoir si l'accès à l'objet avec un autre type (alias) est bien défini ou non. Voici une liste de Référence cpp :

  • AliasedType et DynamicType sont similaire .
  • AliasedType est la variante (éventuellement qualifiée cv) signée ou non signée de DynamicType.
  • AliasedType est std::byte (depuis C++17), char, ou unsigned char : cela permet d'examiner la représentation objet de n'importe quel objet comme un tableau d'octets.

Il manque à cette liste :

  • L'objet pointé de DynamicType est interchangeable par pointeur avec un autre objet d'AliasedType.

si vous effectuez un cast entre deux types incompatibles, (...), est-il sûr de l'utiliser ?

Cela dépend de ce que vous entendez par "utilisation". Si vous voulez dire indirectement par le pointeur réinterprété et accéder à l'objet par le type "incompatible", alors non, ce n'est pas sûr en général.

et le résultat de ce cast est le seul pointeur qui pointe vers la mémoire qu'il utilise dans tout le programme

Ce n'est pas pertinent. Dans la plupart des cas, il est pratiquement impossible pour un compilateur de prouver que cela est vrai.

Est-il sûr alors de le remettre dans son type original et de l'utiliser en supposant la variable où il est stocké ?

En supposant que la distribution vers l'autre type était bien formée au départ, la conversion vers le type original est toujours sûre.

3voto

SergeyA Points 2159

Tout d'abord, l'utilisation de reinterpret_cast en soi ne déclenche pas de comportement indéfini, mais l'utilisation de ses fruits le fera très probablement - nous continuerons donc à considérer l'option reinterpret_cast elle-même, plutôt que son utilisation. Il faut également noter que le casting vers et vers retour est défini, tant que les deux types sont de la même taille, mais il y a peu de cas où l'on utiliserait reinterpret_cast pour cela - dans la plupart des cas, les gens utiliseraient void* comme intermédiaire et static_cast ferait.

La règle stricte du crénelage a toujours fait l'objet d'une certaine controverse. Elle permet certaines optimisations du compilateur, mais elle inhibe également de nombreuses techniques de sérialisation des entités, qui se sont avérées très utiles au fil du temps.

Il y a des cas très légitimes où la sérialisation des entités est utilisée, et un grand nombre de systèmes utilisent la sérialisation des entités. reinterpret_cast a reconstruire les données. Certes, cela implique techniquement un comportement non défini, mais c'est un compromis que les gens sont souvent prêts à faire.

Avec l'introduction de bit_cast en C++20, j'espère que la controversée reinterpret_cast verra que c'est le crépuscule.

1voto

einpoklum Points 2893

pourquoi existe-t-il ?

  1. Parce que n'importe quel matériel de traitement peut le faire.
  2. Parce que vous pouviez le faire en C, et le C++ s'est développé à partir du C.
  3. Parce qu'il est utile dans les cas où il est difficile, voire impossible, de le remplacer.
  4. ... et si vous vouliez le remplacer, ce pourrait être avec à peu près la même chose, par exemple une union où vous écrivez un membre et en lisez un autre.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X