Załóżmy, że biblioteka C musi udostępniać szczegóły struktury z kodem aplikacji i musi zachować kompatybilność wsteczną API i ABI. Próbuje to zrobić, sprawdzając rozmiar przekazanej mu struktury.W jaki sposób system sizeof (struct) zapewnia zgodność z ABI?
Powiedzmy, że następująca struktura wymaga aktualizacji. W bibliotece w wersji 1,
typedef struct {
int size;
char* x;
int y;
} foo;
w wersji 2 biblioteki, jest ona zaktualizowana:
typedef struct {
int size;
char* x;
int y;
int z;
} foo_2;
Teraz biblioteka wersja 2 chce sprawdzić, czy aplikacja przechodzi nowy foo_2
lub stary foo
jako argument, arg
, do funkcji. Zakłada ona, że wniosek został ustawiony arg.size
do sizeof(foo)
lub sizeof(foo_2)
i próbuje dowiedzieć się, czy kod aplikacji groks wersji 2.
if(arg.size == sizeof(foo_2)) {
// The application groks version 2 of the library. So, arg.z is valid.
} else {
// The application uses of version 1 of the library. arg.z is not valid.
}
Zastanawiam się, dlaczego nie zawiedzie. W GCC 4.6.3, z opcją -O3, zarówno sizeof(foo)
, jak i sizeof(foo_2)
mają wartość 24. Czy kod biblioteki biblioteki v2 nie zostanie zrozumiany, jeśli aplikacja przechodzi przez strukturę typu foo
lub foo_2
? Jeśli tak, to w jaki sposób to podejście zostało zastosowane?
http://blogs.msdn.com/b/oldnewthing/archive/2003/12/12/56061.aspx
Śledź na pytanie: Czy istnieje dobry powód, aby faworyzować użycie sizeof(struct)
dla dyskryminacji wersja? Jak podkreślono w komentarzach, dlaczego nie użyć jawnego członka version
we współużytkowanej strukturze?
Skąd się bierze 24? –
To prawdopodobnie nie zadziała. 'sizeof' jest kompilacją i chcesz sprawdzić rozmiar w * środowisku wykonawczym *. –
@BasileStarynkevitch: Hm, co? Chcemy wiedzieć, z której wersji struktury korzystał dzwoniący, a nie od kanclerza, więc dobrze wygląda z tego kierunku. Mimo to, kolczaste ma rację, że na większości platform 64-bitowych, wskaźnik jest wyrównany do 8 bajtów i ma rozmiar 4, a zatem nie ma różnicy wielkości między tymi dwiema strukturami. – Deduplicator