可以将__attribute__((__may_alias__))用作指向类实例而不是类定义本身的指针吗?

G++: Can __attribute__((__may_alias__)) be used for pointer to class instance rather than to class definition itself?

本文关键字:定义 指针 may attribute alias 实例      更新时间:2023-10-16

我正在寻找以下问题的答案:may_alias是否适合作为指向某些类Foo对象的指针的属性?还是只能在类级别使用?

考虑以下代码(它基于一个更复杂的真实示例):

#include <iostream>
using namespace std;
#define alias_hack __attribute__((__may_alias__))
template <typename T>
class Foo
{
private:
    /*alias_hack*/ char Data[sizeof (T)];
public:
    /*alias_hack*/ T& GetT()
    {
        return *((/*alias_hack*/ T*)Data);
    } 
};
struct Bar
{
    int Baz;
    Bar(int baz)
      : Baz(baz)
    {}
} /*alias_hack*/; // <- uncommeting this line apparently solves the problem, but does so on class-level(rather than pointer-level)
// uncommenting previous alias_hack's doesn't help
int main()
{
    Foo<Bar> foo;
    foo.GetT().Baz = 42;
    cout << foo.GetT().Baz << endl;
}

有没有办法告诉gcc,单指针may_alias一些另一个?

顺便说一句,请注意gcc对这种问题的检测机制是不完善的,所以很容易让这个警告消失,而不会真正解决问题。

考虑下面的代码片段:
#include <iostream>
using namespace std;
int main()
{
    long i = 42;
    long* iptr = &i;
    //(*(short*)&i) = 3; // with warning
    //(*(short*)iptr) = 3; // without warning
    cout << i << endl;
}

取消其中一行的注释,以查看编译器输出的差异

简单的回答——对不起,不行。

__attrbite__向编译器提供指令。对象存在于被执行程序的内存中。因此,__attribute__列表中的任何内容都与运行时执行无关。

Dimitar是正确的。May_alias是一个类型属性。它只能应用于类型,而不能应用于该类型的实例。你想要的是gcc所说的"可变属性"。为一个特定的指针禁用优化并不容易。如果你用这个指针调用一个函数,编译器会怎么做?函数可能已经编译了,并且将基于传递给函数的类型而不是基于指针中存储的地址(现在您应该看到为什么这是一个类型属性)

现在,根据你的代码,类似的东西可能会起作用:

#define define_may_alias_type(X) class X ## _may alias : public X { } attribute ((may_alias));

你只是传递你的指针作为Foo_may_alias *(而不是Foo *),当它可能别名。这是很粗糙的

写下你关于警告的问题,这是因为-Wall默认为-Wstrict-aliasing=3,这不是100%准确。实际上,-Wstrict-aliasing从来没有100%准确,但根据水平,你会得到或多或少的假阴性(和假阳性)。如果将-Wstrict-aliasing=1传递给gcc,您将看到

的警告。