I mają strukturę, która ma na celu przechowywania danych określonych przez użytkownika (to jest z wtyczką). Ma taki char[]
z danym maksymalnym rozmiarem, aby przechowywać te dane.Typ paronomazja char [] i dereferencing
struct A
{
// other members omitted
// data meant to be type punned, only contains PODs
char data[256];
};
Potem jest struktura użytkownik próbka, która ma statyczną funkcję do oddania się od A
.
struct B
{
int i;
double d;
static B& FromA_ref(A& a)
{
// static_assert that sizeof(B) < sizeof(A::data)
return * reinterpret_cast<B*>(a.data);
}
};
Kompiluję z g++ -O3 -std=c++0x -Wall -o test test.cpp
(GCC 4.6.1).
Spowoduje to wygenerowanie ostrzeżenia o numerze dereferencing type-punned pointer will break strict-aliasing rules
. Myślałem, że będzie dobrze, ponieważ użyłem char[]
jako pamięci masowej, która według mnie byłaby zgodna z tymi samymi regułami, co char*
. Uważam to za dziwne, że tak nie jest. Czy nie? Cóż ... Nie mogę tego teraz zmienić, więc przejdźmy dalej.
Teraz rozważmy następujący sposób:
struct B
{
....
static B* FromA_ptr(A& a)
{
// static_assert that sizeof(B) < sizeof(A::data)
return reinterpret_cast<B*>(a.data);
}
}
Ponieważ nie jestem dereferencji niczego tutaj GCC nie żadnego ostrzeżenia wyjście. Nie dzieje się tak również wtedy, gdy później używam wskaźnika do B
.
A a;
auto b = B::FromA_ptr(a);
b->i = 2; // no warnings.
Ale czy można to bezpiecznie zrobić? Czuję, że pracuję nad rozwiązaniem problemu, zamiast go rozwiązywać. Dla mnie ->
nadal w jakiś sposób usuwa odwołanie do zmiennej.
Czy istnieje lepszy sposób osiągnięcia tego efektu? TO ZNACZY. otrzymasz modyfikowalne odniesienie (lub wskaźnik) odlane z magazynu wewnątrz innej struktury? (Unia nie będzie działać, ponieważ zbiór przechowywanych typów nie jest znany, gdy zdefiniowano A
, a niektóre mogą być dodane za pomocą wtyczek, memcpy
zmusi mnie do skopiowania danych tam iz powrotem, chociaż wydaje się, że jest to jedyny bezpieczny sposób, więc daleko)
Nie jestem ekspertem, ale czy szukasz atrybutu '__may_alias__'? http://blog.worldofcoding.com/2010/02/solving-gcc-44-strict-aliasing-problems.html –
W każdym razie, jak sobie radzisz z problemem wyrównania? – curiousguy
@cualnyguy: do tej pory nie, ale powinienem. Na x86 myślę, że może pogorszyć wydajność w najgorszym. Mam nadzieję, że '__attribute __ ((wyrównane (8));' byłoby wystarczające, ponieważ nie próbuję automatycznie wektoryzować czegokolwiek. Prawdopodobnie "may_alias" już mówi GCC, aby zwracał uwagę na wyrównanie, zanim zrobi zbyt wiele dziwnych rzeczy. –