Я посмотрел на выходе ассемблера для следующего фрагмента кода, и я был поражен:Lambdas как закрытие брать окружающая среда. Решающая роль RIP зарегистрировать
int x=0, y=0; // global
// r1, r2 are ints, local.
std::thread t([&x, &y, &r1, &r2](){
x = 1;
r1 = y;
});
!std::thread t([&x, &y, &r1, &r2](){
<lambda()>::operator()(void) const+0: push %rbp
<lambda()>::operator()(void) const+1: mov %rsp,%rbp
<lambda()>::operator()(void) const+4: mov %rdi,-0x8(%rbp)
<lambda()>::operator()(void) const+18: mov -0x8(%rbp),%rax
<lambda()>::operator()(void) const+22: mov (%rax),%rax
! x = 1;
<lambda()>::operator()(void) const()
<lambda()>::operator()(void) const+8: movl $0x1,0x205362(%rip) # 0x6062ac <x>
! r1 = y;
<lambda()>::operator()(void) const+25: mov 0x205359(%rip),%edx # 0x6062b0 <y>
<lambda()>::operator()(void) const+31: mov %edx,(%rax)
!
!});
<lambda()>::operator()(void) const+33: nop
<lambda()>::operator()(void) const+34: pop %rbp
<lambda()>::operator()(void) const+35: retq
Почему адрес x
, y
определяются относится к RIP
, RIP
- указатель инструкции, поэтому он кажется диким. Особенно, я никогда не видел ничего подобного. (Возможно, я не видел много вещей :)).
Единственное объяснение, которое приходит мне в голову, состоит в том, что лямбда является закрытием, а переменные среды из определенного места имеют что-то общее с RIP
.
RIP относительная адресация была введена в x86_64. Ссылка на память относится к указателю инструкции. Это полезно при создании независимого от позиции кода. Вы можете найти описание здесь: https://www.tortall.net/projects/yasm/manual/html/nasm-effaddr.html –
http://stackoverflow.com/q/18447627/995714, http: // stackoverflow .com/q/3250277/995714 –
PIC хорош в 64-битной среде, так как операторы могут быть 32-разрядными. –