Nous venons de mettre à niveau notre compilateur à GCC 4.6 et nous obtenons maintenant certains de ces avertissements. Au moment où notre code de code n'est pas dans un état d'être compilé avec C ++ 0x et de toute façon, nous ne voulons pas l'exécuter dans Prod (au moins pas encore) - alors j'avais donc besoin d'une solution pour supprimer cet avertissement.
Les avertissements se produisent généralement à cause de quelque chose comme ceci: p> plus tard, ceci est utilisé de la manière suivante p> Pour lire, mettre à jour et revenir par exemple, la distribution suivante utilisée pour arriver p> ceci était correct avec 4.4; en 4.6 ce qui précède génère: p> AVERTISSEMENT: le pointeur punne de type cassera des règles strictes-aliasing p>
blockQuote> Un moyen propre pour supprimer cette erreur consiste à utiliser un «code> union code>, cependant, comme je l'ai dit, nous ne pouvons pas utiliser C ++ 0x (et donc des syndicats non restreints), donc J'ai employé le Horrible Hack Hack fort> ci-dessous - maintenant, l'avertissement est parti, mais je suis susceptible d'invoquer des démons nasaux? P> ceci semble Travailler Bien (voir exemple simple ici: http://www.ideone.com/9P3MS ) et génère non Avertissements, est-ce que ça va (pas dans le sens stylistique) d'utiliser ceci jusqu'à C ++ 0x? p> Remarque: je ne veux pas utiliser EDIT STRUT>: Il semble que je me trompais, le même avertissement est là sur 4.4, je suppose que nous ne l'avons cueilli récemment avec le changement (il a toujours été improbable Être un problème de compilateur), la question se tient toujours. P> ceci ne génère pas réellement un avertissement. En conséquence, mon exemple simple sur l'idéone est imparfait et plus important encore mon hack avant ne corrige pas l'avertissement fort>, le seul moyen de résoudre ce problème est de diviser l'appel de la fonction de la fonte - puis de la distribution être laissé comme un
-fno-strict-aliasing code> Généralement ... P>
reterpret_cast code>. p> p>
4 Réponses :
Pourquoi ne pas utiliser: et ensuite: p> Je ne pense pas qu'un syndicat est le meilleur moyen, il peut aussi être problématique. À partir des DOCS GCC: P> `-fstrict-aliasing'
Allows the compiler to assume the strictest aliasing rules
applicable to the language being compiled. For C (and C++), this
activates optimizations based on the type of expressions. In
particular, an object of one type is assumed never to reside at
the same address as an object of a different type, unless the
types are almost the same. For example, an `unsigned int' can
alias an `int', but not a `void*' or a `double'. A character type
may alias any other type.
Pay special attention to code like this:
union a_union {
int i;
double d;
};
int f() {
a_union t;
t.d = 3.0;
return t.i;
}
The practice of reading from a different union member than the one
most recently written to (called "type-punning") is common. Even
with `-fstrict-aliasing', type-punning is allowed, provided the
memory is accessed through the union type. So, the code above
will work as expected. However, this code might not:
int f() {
a_union t;
int* ip;
t.d = 3.0;
ip = &t.i;
return *ip;
}
@Nim: Y a-t-il une raison pour laquelle non? Peut-être avoir un constructeur factice qui n'écrit pas le vdata code> et juste à la place - nouveau lorsque vous souhaitez l'utiliser.
Il y a des complications que je n'ai pas mentionnées, le pr quelque type code> est une variante, et je tiens à utiliser le fait que l'attribution au même type détenu par la variante est moins chère que la construction de la valeur par défaut ( puis reconstruisant le nouveau type).
Je serais plus préoccupé par certains_size ne pas être assez gros, franchement. Cependant, il est em> légal to alias tout type avec un Aussi, je remetterais ce genre de conception. Sauf si vous implémentez char * code>. Donc simplement faire
reterpret_cast
boost :: variante code> ou quelque chose de similaire, il n'y a pas beaucoup de raisons de l'utiliser. P>
Il est légal d'alias tout type avec char * code>, mais il n'est pas nécessairement légal d'alias
char * code> avec n'importe quel type. Les règles de type-Pun ne sont pas symétriques par rapport au type réel de l'objet et le type utilisé pour y accéder.
Tandis que les règles de revêtement de type ne sont pas en général symétriques, elles sont symétriques par rapport à char code> - vous pouvez alias tout type avec
char code> et peut alias
char code> avec n'importe quel type. Étant donné que ce code est un aliasing avec
char code>, l'avertissement du compilateur est incorrect.
@Chris: check 3.10 / 15. Il ne dit pas qu'un objet dont le type dynamique est Char code> est accessible via un lvalue de n'importe quel type. Différents cas de
Automype code> sont corrects, mais les seuls UDT qui sont qualifiés sont un agrégat ou un syndicat avec un
char code>,
signé Char code>,
non signé Char code> membre ou version qualifiée de CV d'un de ceux-ci.
Automatique code> pourrait ne pas être un tel agrégat ou un tel syndicat. Il n'y a pas de symétrie. Donc, cet alias n'est que légal depuis que le type dynamique de l'objet est
quelqueye code>, grâce au placement nouveau. S'il y a quelque part ailleurs dans la norme qui permet à tout autre aliasing, je l'ai manqué.
@Stevejessop: Je considère cela un bogue dans la norme alors. Il faut y avoir un moyen d'avoir une blob de mémoire non ancrée d'un nombre spécifique d'octets. S'il n'y a pas, une manière approuvée de faire cela doit être créée. Si rien d'autre, il est pratiquement impossible de mettre en œuvre un allocateur en C ++.
@Omnifaous: Il y a une maladresse là-bas - placement Nouveau code> vous donne un moyen de convertir la mémoire brute (
char code>) dans votre objet de type
Automype code> sans Avez-vous déjà eu à vous référer à tout autre lvalue, puisque la mise en œuvre prend en charge cela. Clairement, ce n'est pas la manière dont C résout le problème, cependant et que les types de POD ont des règles sur la durée de vie et le fait que vous puissiez la mettre fin à la "réutilisation" de leur mémoire. Cette "réutilisation" pourrait interagir avec les règles d'aliasing d'une certaine manière, je ne me souviens pas. Si cela implique une symétrie non indiquée dans 3,10 / 15, mes excuses.
@Stevejessop Il s'agit d'un état de fait confus, triste et effrayant: il existe différentes interprétations des règles d'aliasing, non seulement par un programmeur aléatoire C ++, également par des implémentations de compilateur (au moins GNU). Et une interprétation, le plus fort, signifie que vous ne pouvez pas avoir d'allocator personnalisé en C / C ++, fin de l'histoire. B> La seconde interprétation moins stricte signifie que Vous ne pouvez pas avoir d'allocator personnalisé en C B> mais le placement-nouveau vous sauve. Veuillez noter que la norme ISO C semble avoir une sémantique aloritable assez différente (et l'OMI Le Comité C est devenu un aliasing Crazy WRT).
template <class T> struct DataPage { alignof(T) char vData[sizeof(T)]; };
Malheureusement, je ne peux pas utiliser ici un modèle, car nous utilisons un mécanisme pour étendre pr quelque type code> de telle sorte que la compatibilité ascendante soit maintenue avec des sorties plus anciennes - en conséquence, toutes les rejets doivent avoir suffisamment de stockage pour tenir compte de la comptabilisation. Modifications potentielles à
ATTRAINTYPE CODE> ...
SomeDataPage page; SomeType *data = new(page.vData) SomeType(); // non-trivial constructor data->some_member();
Merci pour la réponse, je pense que j'ai mis à jour la question, la seule façon de pouvoir éviter que l'avertissement était de diviser la distribution (malheureusement, le nouvel opération code> nouvelle code> se produit au moment de l'initialisation et à l'appel à Certain_member () CODE> arrive pendant la course normale) - il y a donc maintenant un
reterpret_cast code> comme j'ai ajouté à la modification. C'est la seule façon de l'obtenir pour supprimer l'avertissement. J'aurais dû ajouter ceci comme une réponse - mais je n'ai jamais eu de route ...
@NIM Le problème ici est que, en décomposant les opérations, vous ne réparez pas le problème sous-jacent (s'il y a vraiment un problème sous-jacent), vous faites simplement que le compilateur vous avertit.
AFAIK Il n'y a pas de problème sous-jacent, j'utilise le placement nouveau pour construire l'objet; IMO, c'est un avertissement parasite qui devait être réduit au silence dans ce cas spécifique - sans que le type d'interrupteur d'avertissement d'avertissement.
@Nim mon interprétation est également qu'il s'agit d'un avertissement parasite; La question que j'ai avec les règles d'aliasing strictes est que les règles ne sont pas assez claires pour tout le monde, en particulier des écrivains compilateurs.
Je pense qu'après que vous avez fait
nouveau (page.vdata) Automype () code>, le type réel de l'objet situé au même endroit que
page.vdata code> est
mérite certains code>, comme c'est la dernière chose qui est stockée là-bas, et donc le type de jeu de mots est légal. L'avertissement déclenché par la distribution ne sait probablement pas avec certitude que vous avez fait ce placement nouveau, cependant. Si j'ai raison pour que votre code d'origine soit bien correct, alors n'assumant aucun bogue dans GCC, l'horrible piratage devrait être ok aussi (puis de la définition de
REINIERPRET_CAST > rend le pointeur résultant de la même manière). Pas sûr, cependant.
@Steve, semble être comme si j'avais tort, l'avertissement est là dans 4,4, tout aussi - tout simplement pas ramassé. La question sur le hack est toujours debout.
" Cela ne génère pas en réalité un avertissement. En conséquence, i>" avec quelles options?
@CuciousGuy,
-wall code> si je me souviens bien ..
@Nim vous voudrez peut-être réessayer avec une certaine optimisation.
@Cuciousguy,
-O3 code>, je n'ai pas vu les avertissements ...
@Nim il n'est pas garanti, mais en général, plus d'optimisation signifie plus d'analyse de code signifie plus d'avertissements.