Перейти к основному содержимому

Лабораторная работа №5. Компиляторы

Цель работы:

Изучить основы работы с компилятором Microsoft CL (Command Line Compiler) для компиляции и отладки программ на языке C++. В рамках работы студенты научатся компилировать простые программы, настраивать параметры компиляции и использовать отладочные инструменты.

Оборудование и ПО:

  1. Персональный компьютер с установленной операционной системой Windows.
  2. Установленный Microsoft Visual Studio (версии 2019 и выше) или Microsoft Build Tools.
  3. Командная строка Developer Command Prompt (доступна после установки Visual Studio или Build Tools).

Теория

Пошаговое руководство. Компиляция собственной программы на языке C++ из командной строки | Microsoft Docs

Справочник по компоновщику MSVC | Microsoft Docs

Процесс компиляции программ на C++

Задачи:

  1. Ознакомиться с основными командами компилятора Microsoft CL.
  2. Написать и скомпилировать простую программу на C++.
  3. Настроить параметры компиляции (например, уровень оптимизации, генерация отладочной информации).
  4. Отладить программу с использованием отладчика.
  5. Проанализировать различия в производительности программы при различных уровнях оптимизации.

Ход работы:

1. Введение в компилятор Microsoft CL

Microsoft CL — это компилятор, который позволяет компилировать программы на языке C++ из командной строки. Основные команды:

  • cl [options] file.cpp — компиляция и линковка программы.
  • cl /c file.cpp — компиляция без линковки (создание объектного файла).
  • cl /EHsc file.cpp — компиляция с поддержкой обработки исключений в стиле C++.
  • cl /Ox file.cpp — компиляция с максимальной оптимизацией.
  • cl /Zi file.cpp — генерация отладочной информации.

2. Написание простой программы на C++

Создайте текстовый файл main.cpp и напишите в него следующий код:

#include <iostream>

int main() {
int a = 10;
int b = 20;
int sum = a + b;
std::cout << "Sum: " << sum << std::endl;
return 0;
}

3. Компиляция программы

  1. Откройте командную строку Developer Command Prompt.

  2. Перейдите в директорию, где находится файл main.cpp.

  3. Выполните команду для компиляции и запуска программы:

    cl main.cpp
    main.exe

    Проверьте, что программа выводит "Sum: 30".

4. Настройка параметров компиляции

  1. Скомпилируйте программу с поддержкой отладочной информации:

    cl /Zi main.cpp
  2. Скомпилируйте программу с включением максимальной оптимизации:

    cl /Ox main.cpp
  3. Сравните размер полученного исполняемого файла и время выполнения программы при различных уровнях оптимизации.

5. Использование отладчика

  1. Добавьте в программу несколько ошибок, например, неверный тип данных или деление на ноль.

  2. Скомпилируйте программу с параметром /Zi.

  3. Запустите отладчик, выполнив команду:

    devenv main.exe /debugexe

    (Visual Studio автоматически откроется в режиме отладки).

  4. Найдите и исправьте ошибки, используя отладчик (пошаговая отладка, просмотр значений переменных и т.д.).

6. Использование опции /E для препроцессинга кода

Описание: Напишите программу на C++ с использованием различных директив препроцессора, таких как #define, #include, #ifdef, и других. Скомпилируйте программу с использованием опции /E, которая выводит результат препроцессинга (то есть код после обработки всех директив препроцессора) в стандартный вывод без выполнения дальнейшей компиляции.

Задачи:

  1. Напишите программу, которая включает следующие элементы:
    • Несколько макросов, определённых с помощью #define.
    • Условные компиляции с использованием #ifdef и #endif.
    • Включение внешнего заголовочного файла с помощью #include.
  2. Используйте опцию /E для вывода результата работы препроцессора в консоль.
  3. Проанализируйте полученный вывод, объяснив, как были обработаны директивы препроцессора.
  4. Включите в отчет код до и после препроцессинга и опишите изменения, которые произошли в результате применения директив препроцессора.

Пример кода для препроцессинга:

#define PI 3.14159
#define SQUARE(x) ((x) * (x))

#include <iostream>

int main() {
#ifdef DEBUG
std::cout << "Debug mode" << std::endl;
#endif
std::cout << "Area of circle with radius 5: " << PI * SQUARE(5) << std::endl;
return 0;
}

Задачи:

  1. Скомпилируйте программу с использованием опции /E:

    cl /E main.cpp > preprocessed_output.txt

    Вывод перенаправляется в файл preprocessed_output.txt.

  2. Откройте файл preprocessed_output.txt и проанализируйте, как были обработаны макросы, условные компиляции и включения заголовочных файлов.

  3. Определите, какие строки были добавлены, изменены или удалены после работы препроцессора.

Ожидаемый результат: Отчет с анализом работы препроцессора, содержащий исходный код до и после препроцессинга, а также объяснения, что именно изменилось в результате работы директив препроцессора.

7. Анализ производительности

  1. Измерьте время выполнения программы без оптимизации и с максимальной оптимизацией.
  2. Проанализируйте, как оптимизация повлияла на производительность и размер исполняемого файла.

Индивидуальная часть

Исходный код берем согласно вашему номеру по журналу группы. Исходные коды

Задание 0: Основы компиляции

  1. Откомпилировать предоставленную программу из командной строки, указав необходимые параметры: путь к каталогам с заголовочными файлами и lib-файлам (и/или перечень lib-файлов).
  2. Изменить имя генерируемого исполняемого файла (см. параметр /Fe)
  3. Удалить исполняемый файл (.exe) и выполнить только компоновку утилитой link.exe, используя готовый obj-файл.
  4. Сгенерировать результат препроцессинга (см. параметр /E). Проанализировать отличия от исходного текста программы.
  5. Сгенерировать ассемблерный код (см. параметр /FAs).
  6. Включить оптимизацию (см. параметр /O2) и снова сгенерировать ассемблерный код. Найти отличия в фрагментах кода, соответствующих исходному тексту.

Задание 1: Использование опции /Wall для поиска предупреждений

Описание: Напишите программу на C++, которая содержит несколько потенциально проблемных участков кода (например, неинициализированные переменные, неиспользуемые переменные, скрытые ошибки приведения типов). Скомпилируйте программу с использованием опции /Wall, которая включает все предупреждения компилятора.

Задачи:

  • Исправьте все выявленные предупреждения.
  • Объясните, какие типы ошибок и предупреждений были найдены и как они могли бы повлиять на работу программы.

Ожидаемый результат: Программа, которая компилируется без предупреждений, и отчет, объясняющий характер и потенциальное влияние найденных проблем.

Задание 2: Оптимизация кода с использованием опции /O2

Описание: Напишите программу на C++, которая выполняет вычислительно интенсивные задачи, например, сортировку большого массива данных или вычисление чисел Фибоначчи. Скомпилируйте программу с использованием опции /O2, которая включает оптимизации, улучшающие скорость выполнения программы.

Задачи:

  • Измерьте время выполнения программы до и после оптимизации.
  • Проанализируйте, насколько опция /O2 улучшила производительность и объясните, какие виды оптимизаций могут быть применены.

Ожидаемый результат: Программа, которая выполняется быстрее после применения оптимизаций, и отчет с анализом производительности.

Задание 3: Отладка с использованием опции /Zi и символьной отладочной информации

Описание: Создайте программу на C++, которая содержит несколько ошибок, таких как деление на ноль или использование неинициализированных указателей. Скомпилируйте программу с использованием опции /Zi, которая добавляет отладочную информацию, и проанализируйте работу программы с помощью отладчика.

Задачи:

  • Найдите и исправьте ошибки в программе, используя отладчик.
  • Объясните, как опция /Zi помогает в процессе отладки.

Ожидаемый результат: Программа с исправленными ошибками и отчет, описывающий процесс отладки и роль отладочной информации.

Задание 4: Анализ кода с использованием опции /analyze

Описание: Напишите программу на C++, которая содержит потенциальные ошибки, такие как переполнение буфера, нарушение доступа к памяти или неправильное использование указателей. Скомпилируйте программу с использованием опции /analyze, которая выполняет статический анализ кода для поиска потенциальных ошибок.

Задачи:

  • Проанализируйте результаты, предоставленные статическим анализатором, и исправьте найденные ошибки.
  • Опишите, какие ошибки были найдены и как их исправление влияет на стабильность и безопасность программы.

Ожидаемый результат: Программа, свободная от потенциальных ошибок, и отчет, описывающий обнаруженные проблемы и процесс их устранения.

Задание 5: Генерация сборочного кода с использованием опции /FA

Описание: Напишите программу на C++, которая выполняет несколько простых арифметических операций и работы с циклами. Скомпилируйте программу с использованием опции /FA, которая генерирует ассемблерный код из C++ исходников.

Задачи:

  • Изучите сгенерированный ассемблерный код и прокомментируйте его.
  • Объясните, как высокоуровневые конструкции C++ были преобразованы в низкоуровневые инструкции и как это влияет на производительность.

Ожидаемый результат: Отчет с анализом сгенерированного ассемблерного кода и выводами о том, как компилятор преобразует высокоуровневый код в машинные инструкции.

Отчет по лабораторной работе:

  1. Описание целей работы.
  2. Код программы main.cpp.
  3. Результаты компиляции и выполнения программы при различных параметрах компиляции.
  4. Логи отладки и исправления ошибок.
  5. Выводы о влиянии различных параметров компиляции на программу.

Заключение:

В результате выполнения лабораторной работы студенты должны овладеть основными навыками работы с компилятором Microsoft CL, понять, как различные параметры компиляции влияют на конечный исполняемый файл и как использовать отладочные инструменты для поиска и исправления ошибок в коде.