Изучение листинга ассемблирования, генерируемого компилятором C++ - часть 1 - Конструкторы и исключения

ОГЛАВЛЕНИЕ

Конструкторы

Рассматривается ассемблерный код для секции, где вызывается оператор new.

; 23   : SmartString* arr = new SmartString[2];

    push    12  ; 0000000cH
    call    ??2@YAPAXI@Z    ; оператор new
    test    eax, eax
    pop ecx
    je  SHORT $L980
    push    2
    pop ecx
    push    OFFSET FLAT:??0SmartString@@QAE@XZ 
    ; SmartString::SmartString

    push    ecx
    lea esi, DWORD PTR [eax+4]
    push    4
    push    esi
    mov DWORD PTR [eax], ecx
    call    ??_H@YGXPAXIHP6EPAX0@Z@Z
    jmp SHORT $L981
$L980:
    xor esi, esi
$L981:

Функция ??_H@YGXPAXIHP6EPAX0@Z@Z - "итератор конструктора вектора", подобный итератору деструктора вектора.

Его перевод на псевдокод C++ выглядит так

unsigned char* allocated = 
    new unsigned char[12]; //Выделить 12 байтов, 4 байта для размера

if (allocated != NULL)
{
    //Поместить размер в первые четыре байта
    //Фактический массив начинается в выделенном + 4
    *(int*)allocated = 4;
   
    vector_constructor_iterator(allocated + 4,
        4, 2, &SmartString::SmartString);
}

Итератор конструктора вектора работает так же, как итератор деструктора вектора. Он вызывает конструктор для всех элементов в массиве.

Исключения

Во всех примерах была отключена обработка исключений перед компиляцией приложения. Активация обработки исключений заставляет компилятор генерировать много лишнего кода.

Заключение

Были изучены некоторые аспекты внутренних механизмов компилятора C++ с помощью листинга ассемблирования. Изучение листинга ассемблирования дает четкое представление о том, что компилятор делает внутри с кодом C++. Это помогает писать более качественный и эффективный код C++.