G ++: Можно ли использовать __attribute __ ((__ may_alias__)) для указателя на экземпляр класса, а не на само определение класса?

Я ищу ответ на следующий вопрос: 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;
}

Раскомментируйте одну из строк, чтобы увидеть разницу в выводе компилятора.

4

Решение

Димитар это правильно. 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, вы увидите предупреждение для обоих

1

Другие решения

Простой ответ — извините, нет.

__attrbite__ дает инструкции компилятору. Объекты существуют в памяти выполненной программы. Следовательно, ничто в списке __attribute__ не может относиться к выполнению во время выполнения.

2

По вопросам рекламы [email protected]