Kan noen forklare denne definisjonen av 'dirent' struct i Solaris?

stemmer
5

Nylig var jeg ser på 'dirent' struktur (i dirent.h) og var litt forvirret av dens definisjon.

MERK: Denne tekstfilen er fra en Solaris maskin på skolen min.


typedef struct dirent {
    ino_t       d_ino;
    off_t       d_off;
    unsigned short  d_reclen;
    char        d_name[1];
} dirent_t;

Spesielt d_name feltet. Hvordan vil dette arbeidet i operativsystemet? Hvis du trenger å lagre en null terminert streng hva er vitsen med en rekke av en enkelt røye? Jeg vet at du kan få adressen til en rekke av sine første element, men jeg er fortsatt forvirret. Tydeligvis noe som skjer, men jeg vet ikke hva. På min Fedora Linux-system hjemme dette feltet er rett og slett definert som:

char d_name[256];

Nå som gjør mye mer fornuftig for åpenbare grunner. Kan noen forklare hvorfor Solaris header filen definerer struct som det gjør?

Publisert på 18/02/2009 klokken 22:04
kilden bruker
På andre språk...                            


4 svar

stemmer
10

Som andre har påpekt, har det siste medlem av struct ikke har noen sett størrelse. Matrisen er imidlertid lenge gjennomføringen bestemmer det må være å imøtekomme de tegnene den ønsker å legge i det. Den gjør dette ved dynamisk allokering av hukommelse for struct, slik som med malloc.

Det er praktisk å erklære medlem som har størrelse 1, men fordi det er lett å finne ut hvor mye minne som er okkupert av en direntvariabel d:

sizeof(dirent) + strlen(d.d_name)

Ved hjelp av størrelse 1 fraråder også mottaker av slike struct verdier fra å prøve å lagre sine egne navn på det i stedet for å fordele sine egne direntverdier. Bruke Linux definisjon, er det rimelig å anta at noen direntverdi du har vil acept en 255-tegns streng, men Solaris gir ingen garanti for at dens direntverdier vil lagre noen flere tegn enn de må.

Jeg tror det var C 99 som introduserte et spesielt tilfelle for den siste medlem av en struct. Struct kan bli erklært som dette i stedet:

typedef struct dirent {
  ino_t d_ino;
  off_t d_off;
  unsigned short d_reclen;
  char d_name[];
} dirent_t;

Matrisen har ikke deklarert størrelse. Dette er kjent som den fleksible matrisen medlem . Det oppnår det samme som Solaris-versjonen, bortsett fra at det er ingen illusjon om at struct av seg selv kunne holde noen navn. Du vet ved å se på det at det er mer til det.

Bruke "fleksible" erklæringen, vil mengden minne okkupert justeres slik:

sizeof(dirent) + strlen(d.d_name) + 1

Det er fordi det fleksible matrisen delen ikke faktor i størrelsen av struct.

Grunnen til at du ikke ser fleksible erklæringer sånn oftere, spesielt i OS bibliotek kode, er trolig på grunn av kompatibilitet med eldre kompilatorer som ikke støtter at anlegget. Det er også for kompatibilitet med kode skrevet for å målrette den gjeldende definisjonen, som ville bryte hvis størrelsen på struct endret sånn.

Svarte 18/02/2009 kl. 23:58
kilden bruker

stemmer
5

Dette er et mønster som brukes i C, for å indikere en vilkårlig lengde grupperingen ved hver ende av en struktur. Arrays i C har ingen innebygde grensekontroll, så når koden din prøver å få tilgang til streng som starter ved d_name, vil den fortsette forbi enden av strukturen. Dette er avhengig av readdir()vil tildele nok minne til å holde hele strengen pluss avslutnings nul.

Svarte 18/02/2009 kl. 22:11
kilden bruker

stemmer
5

Den dirent struct vil umiddelbart bli fulgt i minnet av en blokk med minne som inneholder resten av navnet, og at minnet er tilgjengelig gjennom d_name feltet.

Svarte 18/02/2009 kl. 22:10
kilden bruker

stemmer
1

Det ser ut som en mikro-optimalisering til meg. Navnene er vanligvis kort, så hvorfor tildele plass som du vet vil gå ubrukt. Dessuten kan Solaris støtter navn som er lengre enn 255 tegn. For å bruke en slik struct du bare tildele nødvendig plass og ignorere ment rekke størrelse.

Svarte 18/02/2009 kl. 22:12
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more