2013-04-29 5 views
3

Я ищу ответ на следующий вопрос: may_alias подходит как атрибут для указателя на объект некоторого класса Foo? Или он должен использоваться только на уровне класса?G ++: Может ли __attribute __ ((__ may_alias__)) использоваться для указателя на экземпляр класса, а не на определение класса?

Рассмотрим следующий код (он основан на реальном примере, который является более сложным):

#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; 
} 

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

ответ

1

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

2

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

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

+0

Не понимаю. Я не знаю механизм управления gcc строгого псевдонима (и связанного с ним материала, как этот атрибут 'may_alias'), но я не вижу проблемы с отключением некоторой оптимизации для чтения/записи, которые используют один конкретный указатель. –

+0

Или вы подразумеваете, что, например, для следующего фрагмента кода 'Foo foo; Foo alias_hack * fooPtr; 'запись с использованием fooPtr, а затем чтение с использованием foo напрямую может привести к неправильному значению из-за оптимизации? Но опять же, я не вижу проблем с этим, я не отмечал «foo» с необходимым атрибутом, но я сделал это для fooPtr. –

+0

Может быть, я просто что-то пропустил –