Компілятор visual studio (початок роботи), myblog

Це поки що лише чернетка

Розглянемо наступний простий приклад консольного додатку Windows в якому друкуються всі параметри, що передаються через командний рядок, і змінні оточення (envp - це покажчик на масив, що містить змінні оточення з їхніми значеннями, розділені знаком рівності (=)):

.bat файл, що компілює цей приклад, має вигляд:

При цьому передбачається наступне розташування файлів

Компілятор visual studio (початок роботи), myblog

У всіх Windows-додатках має бути вхідні функція. за реалізацію якої відповідаєте ви. Існує дві такі функції:

_tWinMain і _tmain це насправді макроси, які розкриваються як WinMain або wWinMain для _tWinMain і main або wmain для _tmain в залежності від того використовується Unicode чи ні.

Насправді вхідні функція операційною системою не викликається. Замість цього відбувається звернення до стартової функції з бібліотеки C / C ++. заданої під час компонування параметром -entry: командного рядка. Вона инициализирует бібліотеку С / С ++, щоб можна було викликати такі функції, як malloc і free. а також забезпечує коректне створення будь-яких оголошених вами глобальних і статичних С ++ - об'єктів до того, як починається виконання вашого коду. У наступній таблиці показано, в яких випадках реалізуються ті чи інші вхідні функції.

Типи додатків і відповідні їм вхідні функції

Компоновщик відповідає за вибір відповідної стартовою функції з бібліотеки С / С ++ при компонуванні виконуваного файлу. Якщо заданий ключ / SUBSYSTEM: WINDOWS. компоновщик шукає в коді функцію WinMain або wWinMain. Якщо цих функцій немає, компонувальник повідомляє про помилку "unresolved external symbol". В іншому випадку компоновщик вибирає WinMainCRTStartup або wWinMainCRTStartup, відповідно.

Аналогічним чином, якщо заданий ключ / SUBSYSTEM: CONSOLE. компоновщик шукає в коді функцію main або wmain і вибирає відповідно mainCRTStartup або wmainCRTStartup; якщо в коді немає ні main, ні wmain, повідомляється про ту ж помилку - "unresolved external symbol".

Але мало хто знає, що в проекті можна взагалі не вказувати ключ / SUBSYSTEM компоновщика. Якщо ви так і зробите, компонувальник буде сам визначати підсистему для вашого застосування. При компонуванні він перевірить, яка з чотирьох функцій (WinMain, wWinMain, main або wmain) присутній у вашому коді, і на підставі цього Оберіть підсистему і стартову функцію з бібліотеки С / С ++.

Тепер кілька зауважень по .bat файлу і ключам компілятора і компоновщика

При створенні .bat файлу потрібно чітко стежити за тим, щоб створюваний текстовий файл мав формат завершення рядка в стилі Windows або Unix. але не Mac. інакше bat файл просто не буде запускатися.

Для нормальної роботи компілятора перед викликом cl.exe або link.exe необхідно викликати call "% vc_path% vcvarsall.bat" x86. Цей bat файл инициализирует змінні оточення INCLUDE. LIB. LIBPATH. PATH і деякі інші необхідні для роботи cl.exe і link.exe. Наприклад, в моєму випадку було

При виклику cl.exe використовувалися наступні ключі:

  • / С - компіляція без зв'язування
  • / ZI - компілятор включає зневадження в базу даних програми (тільки для x86)
  • / Nologo - пригнічує відображення інформації про компіляторі
  • / W3 - встановлює рівень попереджень компілятора на 3 рівень
  • / Od - відключає оптимізацію (так як / Od запобігає переміщенню коду, установка цього ключа полегшує процес налагодження)
  • / Oy - запобігає створення покажчиків фрейма в стеці виклику, / Oy- відключає така поведінка (тільки для x86)
  • / D "_DEBUG" - визначається при компіляції з ключами / LDd, / MDd і / MTd
  • / D "_WINDOWS" - визначає, що цільова OS - Windows
  • / D "UNICODE" - вказує компілятору на необхідність використовувати в додатку версії Win API функцій для роботи з Unicode
    Наприклад, ось фрагмент з WinUser.h. Тобто, якщо ми при компіляції вказуємо / D "UNICODE" і в своєму коді викликаємо CreateWindowEx. то насправді відбувається звернення до CreateWindowExW
  • / D "_UNICODE" - подібно UNICODE вказує на використання в додатку версій функцій з бібліотеки С для роботи з Unicode рядками. Так, наприклад, в заголовки TChar.h можна знайти визначення наступного макросу: Тепер при виклику _tcslen і певному _UNICODE виклик дозволяється в wcslen. в іншому випадку - в strlen. За замовчуванням в нових С ++ - проектах Visual Studio визначено _UNICODE (як і UNICODE)
  • / Gm - включає мінімальну перекомпіляцію, яка дозволяє перекомпілювати тільки файли з зміненим вихідним кодом
  • / EHsc - перехоплюються тільки С ++ виключення і гарантується, що зовнішні З функції, ніколи не викинуть С ++ виняток

/ RTC (Run-Time Error Checks) (Перевірка помилок часу виконання)

/ RTC1 - еквівалентно / RTCsu

/ RTCs - включає перевірку стекового фрейма часу виконання, що означає:

  • ініціалізацію локальних змінних ненульовими значеннями. Це дозволяє ідентифікувати баги, які не виявляються в отладочной збірці. Більшої ймовірність, що змінна в стеці залишатиметься нульовою в отладочной збірці ніж в рілізной збірці, так як компілятор оптимізує стек змінних в рілін збірці. Будучи одного разу використаної пам'ять відведена під стік не обнуляється компілятором. З цього, подальшому не початкові змінні в стеку міститимуть значення залишився від попереднього використання цієї області пам'яті.
  • Перевірка виходу за межі локальних змінних, таких як масиви. / RTCs не визначає вихід за межі при зверненні до пам'яті явилася результатом вирівнювання компілятором положення структури в пам'яті. Таке може статися при використанні вирівнювання (С ++). / Zp або pack або, якщо ви распологайся елементи структури в такому порядку, який змушує компілятор вставляти відступи.
  • Перевірка покажчика стека, що дозволяє визначити руйнування покажчика стека. Руйнування покажчика стека може статися при невідповідності тип дзвінка. Наприклад, використовуючи покажчик на функцію, ви можите викликати функцію з DLL, яка експортується як __stdcall. але ви визначили покажчик на функцію як __cdecl.

зауваження:
стековий фрейм (функції) - область пам'яті, що виділяється щоразу, коли викликається функція, призначається для тимчасового зберігання аргументів і локальних змінних функції.

/ RTCu - змушує компілятор видавати попередження, коли змінна використовується без ініціалізації. Наприклад, команда, яка генерує попередження (4-го рівня) С4701 може також генерувати помилку часу виконання при встановленому ключі / RTCu. Будь-які команди, які генерують попередження компілятора (рівня 1 і 4) С4700. будуть також генерувати помилку часу виконання при встановленому ключі / RTCu.

Проте, розглянемо наступний фрагмент коду:

Post navigation

Leave a Reply Cancel reply