Я ищу ответ на следующий вопрос: 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;
}
Раскомментируйте одну из строк, чтобы увидеть разницу в выводе компилятора.
Димитар это правильно. 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, вы увидите предупреждение для обоих
Простой ответ — извините, нет.
__attrbite__ дает инструкции компилятору. Объекты существуют в памяти выполненной программы. Следовательно, ничто в списке __attribute__ не может относиться к выполнению во время выполнения.