Aliasing (dator)

Inom databehandling beskriver aliasing en situation där en dataplats i minnet kan nås genom olika symboliska namn i programmet . Modifiering av data genom ett namn ändrar alltså implicit värdena som är associerade med alla aliasnamn, vilket kanske inte förväntas av programmeraren. Som ett resultat gör aliasing det särskilt svårt att förstå, analysera och optimera program. Aliasinganalysatorer avser att skapa och beräkna användbar information för att förstå aliasing i program.

Exempel

Buffer-överflöde

Till exempel utför de flesta implementeringar av programmeringsspråket C inte kontroll av arraygränser . Man kan sedan utnyttja implementeringen av programmeringsspråket av kompilatorn och datorarkitekturens assembly-språkkonventioner , för att uppnå aliaseffekter genom att skriva utanför arrayen (en typ av buffertspill ). Detta åberopar odefinierat beteende enligt C-språkspecifikationen; Men många implementeringar av C kommer att visa de aliaseffekter som beskrivs här.

Om en array skapas på stacken , med en variabel utlagd i minnet direkt bredvid den arrayen , kan man indexera utanför arrayen och direkt ändra variabeln genom att ändra det relevanta arrayelementet. Till exempel, om det finns en int- matris av storlek 2 (för detta exempels skull, kallar den arr ), bredvid en annan int- variabel (kalla den i ), skulle arr[2] (dvs. det 3:e elementet) ha alias till i om de ligger intill i minnet.

  

 

        
   

  
    

   0 
    
    
    
  
      
 #  include  <stdio.h>  int  main  ()  {  int  arr  [  2  ]  =  {  1  ,  2  };  int  i  =  10  ;  /* Skriv bortom slutet av arr. Odefinierat beteende i standard C, kommer att skriva till i i vissa implementeringar.  */   arr  [  2  ]  =  20  ;  printf  (  "element 0: %d  \t  "  ,  arr  [  ]);  // matar ut 1  printf  (  "element 1: %d  \t  "  ,  arr  [  1  ]);  // utmatar 2  printf  (  "element 2: %d  \t  "  ,  arr  [  2  ]);  // anger 20, om aliasing inträffade  printf  (  "i: %d  \t\t  "  ,  i  );  //  kan också mata ut 20, inte 10, på grund av aliasing, men kompilatorn kan ha lagrat i ett register och skriva ut 10  /* arr size är fortfarande 2. */  printf  (  "arr size: %lu  \n  "  , (   long  )  (  sizeof  (  arr  )  /  sizeof  (  int  )));  } 

Detta är möjligt i vissa implementeringar av C eftersom en array är ett block av sammanhängande minne, och arrayelement endast refereras till av förskjutningar från adressen till början av det blocket multiplicerat med storleken på ett enda element. Eftersom C inte har någon kontroll av gränser, är indexering och adressering utanför arrayen möjlig. Observera att det tidigare nämnda aliasingbeteendet är odefinierat beteende . Vissa implementeringar kan lämna utrymme mellan arrayer och variabler i stacken, till exempel för att justera variabler till minnesplatser som är en multipel av arkitekturens ursprungliga ordstorlek . C-standarden anger generellt inte hur data ska läggas upp i minnet. (ISO/IEC 9899:1999, avsnitt 6.2.6.1).

Det är inte felaktigt för en kompilator att utelämna aliaseffekter för åtkomster som faller utanför gränserna för en array.

Aliaserade pekare

En annan variant av alias kan förekomma på alla språk som kan referera till en plats i minnet med mer än ett namn (till exempel med pekare ). Se C- exemplet på XOR-swapalgoritmen som är en funktion; det antar att de två pekarna som skickas till den är distinkta, men om de i själva verket är lika (eller alias till varandra) misslyckas funktionen. Detta är ett vanligt problem med funktioner som accepterar pekarargument, och deras tolerans (eller avsaknaden av sådan) för aliasing måste noggrant dokumenteras, särskilt för funktioner som utför komplexa manipulationer på minnesområden som skickas till dem.

Specificerad alias

Kontrollerat aliasbeteende kan vara önskvärt i vissa fall (det vill säga aliasingbeteende som är specificerat, till skillnad från det som aktiveras av minneslayout i C). Det är vanligt i Fortran . Programmeringsspråket Perl specificerar, i vissa konstruktioner, aliasingbeteende , såsom i foreach loops. Detta gör att vissa datastrukturer kan modifieras direkt med mindre kod. Till exempel,

     

    
    
    
    
    


  min  @array  =  (  1  ,  2  ,  3  );  foreach  my  $element  (  @array  )  {  # Öka $element, och därmed  # modifiera @array automatiskt, eftersom $element är ''aliased''  # till vart och ett av @arrays element i tur och ordning.  $element  ++  ;  }  skriv ut  "@array \n"  ; 

kommer att skriva ut "2 3 4" som ett resultat. Om man ville kringgå aliaseffekter kunde man kopiera innehållet i indexvariabeln till en annan och ändra kopian.

Konflikt med optimering

Optimerare måste ofta göra konservativa antaganden om variabler när alias är möjligt. Att till exempel känna till värdet på en variabel (som x är 5) tillåter normalt vissa optimeringar (som konstant fortplantning ). Däremot kan kompilatorn inte använda denna information efter en tilldelning till en annan variabel (till exempel i C, *y = 10 ) eftersom det kan vara så att *y är ett alias för x . Detta kan vara fallet efter en uppgift som y = &x . Som en effekt av denna tilldelning till *y skulle värdet av x också ändras, så att sprida informationen om att x är 5 till påståendena efter *y = 10 skulle vara potentiellt fel (om *y verkligen är ett alias för x ). Men om det finns information om pekare, kan den konstanta spridningsprocessen göra en fråga som: kan x vara ett alias för *y ? Sedan, om svaret är nej, x = 5 spridas säkert.

En annan optimering som påverkas av aliasing är kodomordning. Om kompilatorn bestämmer att x inte är alias av *y , kan kod som använder eller ändrar värdet på x flyttas före tilldelningen *y = 10 , om detta skulle förbättra schemaläggningen eller möjliggöra att fler loopoptimeringar kan utföras.

För att möjliggöra sådana optimeringar på ett förutsägbart sätt specificerar ISO-standarden för programmeringsspråket C (inklusive dess nyare C99 -utgåva, se avsnitt 6.5, stycke 7) att det är olagligt (med vissa undantag) att komma åt samma minnesplats med hjälp av pekare på olika typer. En kompilator kan därför anta att sådana pekare inte är alias. Den här regeln, känd som den strikta aliasingregeln , tillåter ibland imponerande prestandaökningar, men har varit känd för att bryta någon annars giltig kod. Flera programvaruprojekt bryter avsiktligt mot denna del av C99-standarden. Till exempel Python 2.x det för att implementera referensräkning och krävde ändringar av de grundläggande objektstrukturerna i Python 3 för att möjliggöra denna optimering. Linux -kärnan gör detta eftersom strikt aliasing orsakar problem med optimering av inlined kod. I sådana fall, när det kompileras med gcc , anropas alternativet -fno-strict-aliasing för att förhindra oönskade optimeringar som kan ge oväntad kod.

Hårdvarualiasing

Termen aliasing används också för att beskriva situationen där, på grund av antingen ett hårdvarudesignval eller ett hårdvarufel, en eller flera av de tillgängliga adressbitarna inte används i minnesvalsprocessen. Detta kan vara ett designbeslut om det finns fler adressbitar tillgängliga än vad som är nödvändigt för att stödja den eller de installerade minnesenheterna. Vid ett fel kan en eller flera adressbitar kortslutas tillsammans eller tvingas till jord (logisk 0) eller matningsspänningen (logik 1).

Exempel

För det här exemplet, anta en minnesdesign med 8 platser, som endast kräver 3 adresslinjer (eller bitar ) eftersom 2 3 = 8). Adressbitar (benämnda A2 till A0) avkodas för att välja unika minnesplatser enligt följande, på standardmässigt binärt räknarsätt :

A2 A1 A0 Minnesplats
0 0 0 0
0 0 1 1
0 1 0 2
0 1 1 3
1 0 0 4
1 0 1 5
1 1 0 6
1 1 1 7

I tabellen ovan väljer var och en av de 8 unika kombinationerna av adressbitar en annan minnesplats. Men om en adressbit (säg A2) skulle kortslutas till jord, skulle tabellen ändras enligt följande:

A2 A1 A0 Minnesplats
0 0 0 0
0 0 1 1
0 1 0 2
0 1 1 3
0 0 0 0
0 0 1 1
0 1 0 2
0 1 1 3

I detta fall, där A2 alltid är noll, dupliceras de första fyra minnesplatserna och visas igen som de andra fyra. Minnesplatserna 4 till 7 har blivit otillgängliga.

Om denna ändring inträffade till en annan adressbit, skulle avkodningsresultaten bli annorlunda, men i allmänhet skulle effekten vara densamma: förlusten av en enda adressbit halverar det tillgängliga minnesutrymmet, med resulterande duplicering (aliasing) av återstående utrymme.

Se även

externa länkar