gpt4 book ai didi

c++ - gcc:如何正确使用 __attribute((__may_alias__)) 以避免 "derefencing type-punned pointer"警告

转载 作者:太空狗 更新时间:2023-10-29 23:47:18 28 4
gpt4 key购买 nike

我有一些代码使用类型双关来避免必须调用成员“对象”的构造函数和析构函数,除非/直到它确实需要使用该对象。

它工作正常,但在 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;
}

最佳答案

我认为 typedef 混淆了 GCC。这些类型的属性在直接应用于变量定义时似乎效果最好。

这个版本的类(class)适合我(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.]

关于c++ - gcc:如何正确使用 __attribute((__may_alias__)) 以避免 "derefencing type-punned pointer"警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6313050/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com