Il tipo di problema Chandler stava parlando può essere facilmente illustrato con una semplificata strcpy
:
char *stpcpy (char * dest, const char * src);
Durante la scrittura di un'implementazione di questo, è possibile presumere che la memoria indicata da dest
sia completamente separata dalla memoria indicata da src
. Il compilatore) potrebbe voler ottimizzarlo leggendo un blocco di caratteri dalla stringa puntata da src
e scrivendoli tutti contemporaneamente in dest
. Ma se dest
puntava a un byte prima di src
, il comportamento di questo sarebbe diverso da una semplice copia carattere per carattere.
Qui il problema aliasing è che src
può alias dest
, e il codice generato deve essere effettuato meno efficiente di quanto potrebbe essere se src
non è stato permesso di alias dest
.
Il vero strcpy
utilizza una parola chiave in più, Restrict (che è technically only part of C, not C++, che dice al compilatore di supporre che src
e dest
non si sovrappongono, e questo permette al compilatore di generare codice molto più efficiente.
Ecco un esempio ancora più semplice in cui possiamo vedere una grande differenza nel montaggio:
void my_function_1(int* a, int* b, int* c) {
if (*a) *b = *a;
if (*a) *c = *a;
}
void my_function_2(int* __restrict a, int* __restrict b, int* __restrict c) {
if (*a) *b = *a;
if (*a) *c = *a;
}
supporre che questa è una semplificazione di una funzione in cui in realtà aveva senso usare due if-statement anziché solo if (*a) { *b=*a; *c=*a; }
, ma l'intento è lo stesso.
Si può presumere quando si scrive questo a != b
perché c'è qualche motivo per cui non avrebbe senso utilizzare my_function
in questo modo.Ma il compilatore non può supporre che, e fa un negozio di b
e una ri-carico di a
dalla memoria prima di eseguire la seconda linea, per coprire il caso in cui b == a
:
0000000000400550 <my_function_1>:
400550: 8b 07 mov (%rdi),%eax
400552: 85 c0 test %eax,%eax <= if (*a)
400554: 74 0a je 400560 <my_function_1+0x10>
400556: 89 06 mov %eax,(%rsi)
400558: 8b 07 mov (%rdi),%eax
40055a: 85 c0 test %eax,%eax <= if (*a)
40055c: 74 02 je 400560 <my_function_1+0x10>
40055e: 89 02 mov %eax,(%rdx)
400560: f3 c3 repz retq
se togliamo potenziale di aliasing aggiungendo __restrict
, il compilatore genera codice più corto e più veloce:
0000000000400570 <my_function_2>:
400570: 8b 07 mov (%rdi),%eax
400572: 85 c0 test %eax,%eax
400574: 74 04 je 40057a <_Z9my_function_2PiS_S_+0xa>
400576: 89 06 mov %eax,(%rsi)
400578: 89 02 mov %eax,(%rdx)
40057a: f3 c3 repz retq
Perché non chiedi a Chandler Carruth? –
possibile duplicato di [aliasing rigoroso] (http://stackoverflow.com/questions/754929/strict-aliasing) –
Prova a guardare [questo] (http://cslibrary.stanford.edu/104/). In realtà è piuttosto buono.L'aliasing è quando si prende il puntatore di un oggetto anziché dell'oggetto stesso, come spiega. –