Где находится двоичный код для выполнения `std::vector<T>::operator[]`, когда TU, вызывающий эту функцию, скомпилирован C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Где находится двоичный код для выполнения `std::vector<T>::operator[]`, когда TU, вызывающий эту функцию, скомпилирован

Сообщение Anonymous »

Если я скомпилирую следующее с помощью -O3

Код: Выделить всё

#include 
int foo() {
std::vector const v{17,2,3};
return v[0] + v[2];
}
Я получаю сборку

Код: Выделить всё

foo():
mov     eax, 20
ret
(по крайней мере, с Clang).
И я понимаю, как это будет работать при вызове каким-либо другим TU.
Но если я скомпилирую с -O0, я получу следующее:

Код: Выделить всё

_Z3foov:
pushq   %rbp
movq    %rsp, %rbp
subq    $112, %rsp
movl    $17, -84(%rbp)
movl    $2, -80(%rbp)
movl    $3, -76(%rbp)
leaq    -84(%rbp), %rax
movq    %rax, -72(%rbp)
movq    $3, -64(%rbp)
leaq    -85(%rbp), %rcx
movq    %rcx, -32(%rbp)
movq    -32(%rbp), %rax
movq    %rax, -8(%rbp)
movq    -72(%rbp), %rsi
movq    -64(%rbp), %rdx
leaq    -56(%rbp), %rdi
callq   _ZNSt6vectorIiSaIiEEC2ESt16initializer_listIiERKS0_
jmp     .LBB0_1
.LBB0_1:
leaq    -85(%rbp), %rax
movq    %rax, -24(%rbp)
leaq    -56(%rbp), %rdi
xorl    %eax, %eax
movl    %eax, %esi
callq   _ZNKSt6vectorIiSaIiEEixEm
movl    (%rax), %eax
movl    %eax, -108(%rbp)
leaq    -56(%rbp), %rdi
movl    $2, %esi
callq   _ZNKSt6vectorIiSaIiEEixEm
movq    %rax, %rcx
movl    -108(%rbp), %eax
addl    (%rcx), %eax
movl    %eax, -104(%rbp)
leaq    -56(%rbp), %rdi
callq   _ZNSt6vectorIiSaIiEED2Ev
movl    -104(%rbp), %eax
addq    $112, %rsp
popq    %rbp
retq
movq    %rax, %rcx
movl    %edx, %eax
movq    %rcx, -96(%rbp)
movl    %eax, -100(%rbp)
leaq    -85(%rbp), %rax
movq    %rax, -16(%rbp)
movq    -96(%rbp), %rdi
callq   _Unwind_Resume@PLT

__clang_call_terminate:
pushq   %rbp
movq    %rsp, %rbp
callq   __cxa_begin_catch@PLT
callq   _ZSt9terminatev@PLT

.L.str:
.asciz  "cannot create std::vector larger than max_size()"

.L.str.1:
.asciz  "/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/15.0.0/../../../../include/c++/15.0.0/bits/stl_vector.h"

.L__PRETTY_FUNCTION__._ZNKSt6vectorIiSaIiEEixEm:
.asciz  "const_reference std::vector::operator[](size_type) const [_Tp = int, _Alloc = std::allocator]"

.L.str.2:
.asciz  "__n < this->size()"

DW.ref.__gxx_personality_v0:
.quad   __gxx_personality_v0
где _ZNKSt6vectorIiSaIiEEixEm вызывается при вычислении v[0] и v[2]. Но я не совсем понимаю, куда переходят эти два вызова. То есть строка _ZNKSt6vectorIiSaIiEEixEm появляется всего 3 раза, 2 - это вызовы, а один такой:

Код: Выделить всё

.L__PRETTY_FUNCTION__._ZNKSt6vectorIiSaIiEEixEm:
.asciz  "const_reference std::vector::operator[](size_type) const [_Tp = int, _Alloc = std::allocator]"
Как это может привести к извлечению элементов из вектора?
Или, другими словами, если я свяжу указанный выше TU с другим, который его вызывает и возвращает значение, например

Код: Выделить всё

int foo();
int main() {
return foo();
}
где мне найти код, который выполняет v[0] и v[2]? Если его нет в сборке, то его даже нет в бинарнике, верно? Тогда как же работает программа?


Подробнее здесь: https://stackoverflow.com/questions/791 ... hen-a-tu-c
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»