c++ - C++ gcc: 如何正確地使用 __attribute ( ( __may_alias_ _ ) 來避免"derefencing類型punned指針"警告

  显示原文与译文双语对照的内容
58 4

我有一些代碼,使用類型二進位,避免不必要調用"對象"和析構函數的成員構造函數。

它工作正常,但在 G++ 4.4.3下,我得到了這個可怕的編譯器警告:

jaf@jeremy-desktop:~$ g++ -O3 -Wall puns.cpp 
puns.cpp: In instantiation of 『Lightweight<Heavyweight>』:
puns.cpp:68: instantiated from here 
puns.cpp:12: warning: ignoring attributes applied to 『Heavyweight』 after definition
puns.cpp: In destructor 『Lightweight<T>::~Lightweight() [with T = Heavyweight]』:
puns.cpp:68: instantiated from here
puns.cpp:20: warning: dereferencing type-punned pointer will break strict-aliasing rules
puns.cpp: In member function 『void Lightweight<T>::MethodThatGetsCalledRarely() [with T = Heavyweight]』:
puns.cpp:70: instantiated from here
puns.cpp:36: warning: dereferencing type-punned pointer will break strict-aliasing rules

我的代碼嘗試使用gcc的__attribute ( ( __may_alias_ _ ) 來讓gcc知道潛在的別名,但是gcc並不理解我正在嘗試告訴它。,,或者 gcc 4.4.3在__may_alias__屬性上有問題?

複製編譯器警告的玩具代碼如下:

#include <stdio.h>
#include <memory>//for placement new
#include <stdlib.h>//for rand()
/** Templated class that I want to be quick to construct and destroy.
 * In particular, I don't want to have T's constructor called unless
 * I actually need it, and I also don't want to use dynamic allocation.
 **/
template<class T> class Lightweight
{
private:
 typedef T __attribute((__may_alias__)) T_may_alias;
public:
 Lightweight() : _isObjectConstructed(false) {/* empty */}
 ~Lightweight()
 {
//call object's destructor, only if we ever constructed it
 if (_isObjectConstructed) (reinterpret_cast<T_may_alias *>(_optionalObject._buf))->~T_may_alias();
 }
 void MethodThatGetsCalledOften()
 {
//Imagine some useful code here
 }
 void MethodThatGetsCalledRarely()
 {
 if (_isObjectConstructed == false)
 {
//demand-construct the heavy object, since we actually need to use it now
 (void) new (reinterpret_cast<T_may_alias *>(_optionalObject._buf)) T();
 _isObjectConstructed = true;
 }
 (reinterpret_cast<T_may_alias *>(_optionalObject._buf))->DoSomething();
 }
private:
 union {
 char _buf[sizeof(T)];
 unsigned long long _thisIsOnlyHereToForceEightByteAlignment;
 } _optionalObject;
 bool _isObjectConstructed;
};
static int _iterationCounter = 0;
static int _heavyCounter = 0;
/** Example of a class that takes (relatively) a lot of resources to construct or destroy. */
class Heavyweight
{
public:
 Heavyweight()
 {
 printf("Heavyweight constructor, this is an expensive call!n");
 _heavyCounter++;
 }
 void DoSomething() {/* Imagine some useful code here*/}
};
static void SomeMethod()
{
 _iterationCounter++;
 Lightweight<Heavyweight> obj;
 if ((rand()%1000)!= 0) obj.MethodThatGetsCalledOften();
 else obj.MethodThatGetsCalledRarely();
}
int main(int argc, char ** argv)
{
 for (int i=0; i<1000; i++) SomeMethod();
 printf("Heavyweight ctor was executed only %i times out of %i iterations, we avoid %.1f%% of the ctor calls!.n", _heavyCounter, _iterationCounter, 100.0f*(1.0f-(((float)_heavyCounter)/((float)_iterationCounter))));
 return 0;
}
时间:原作者:0个回答

91 3

我認為 typedef 讓GCC困惑。這些屬性在直接應用到變數定義時似乎工作得最好。

這裡版本的類適用於我( GCC 4.6.0 ):

template<class T> class Lightweight
{
private:
//typedef T __attribute((__may_alias__)) T_may_alias;
public:
 Lightweight() : _isObjectConstructed(false) {/* empty */}
 ~Lightweight()
 {
//call object's destructor, only if we ever constructed it
 if (_isObjectConstructed) {
 T * __attribute__((__may_alias__)) p
 = (reinterpret_cast<T *>(_optionalObject._buf));
 p->~T();
 }
 }
 void MethodThatGetsCalledOften()
 {
//Imagine some useful code here
 }
 void MethodThatGetsCalledRarely()
 {
 T * __attribute__((__may_alias__)) p
 = (reinterpret_cast<T *>(_optionalObject._buf));
 if (_isObjectConstructed == false)
 {
//demand-construct the heavy object, since we actually need to use it now
 (void) new (p) T();
 _isObjectConstructed = true;
 }
 p->DoSomething();
 }
 [etc.]
原作者:
...