SlideShare a Scribd company logo
Урок 5. Сборка 64-битного
приложения
Хочется сразу предупредить читателя, что невозможно всесторонне описать процесс сборки 64-
битного приложения. Настройки любого проекта достаточно уникальны, поэтому к адаптации
настроек для 64-битной системы всегда надо подходить внимательно. В уроке будут описаны
только общие шаги, которые важны для любого проекта. Эти шаги подскажут вам с чего начать
процесс.


Библиотеки
Прежде чем попытаться собрать ваше 64-битное приложение, проверьте, что установлены все
необходимые версии 64-битных библиотек и к ним корректно прописаны пути. Например, 32-
битные и 64-битные библиотечные lib файлы отличаются и, как правило, находятся в различных
каталогах. Исправьте найденные недочеты.

Примечание. Если библиотеки представлены в исходных кодах, то должна присутствовать 64-
битная конфигурация проекта. Учтите, что самостоятельно занимаясь модернизацией
библиотеки для сборки ее 64-битной версии, вы можете нарушить лицензионные соглашения.


Ассемблер
Visual C++ не поддерживает 64-битный встроенный ассемблер. Вы должны использовать или
внешний 64-битный ассемблер (например, MASM), или иметь реализацию той же
функциональности на языке Си/Си++.


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

void foo(unsigned char) {}

void foo(unsigned int) {}

void a(const char *str)

{

    foo(strlen(str));

}

Данный код успешно компилируется в 32-битном режиме. А в 64-битном компилятор Visual C++
выдаст сообщение:

error C2668: 'foo' : ambiguous call to overloaded function
.xxxx.cpp(16): could be 'void foo(unsigned int)'

    .xxxx.cpp(15): or 'void foo(unsigned char)'

    while trying to match the argument list '(size_t)'

Функция strlen() возвращает тип size_t. На 32-битной системе тип size_t совпадает с типом unsigned
int и компилятор выбирает для вызова функцию void foo(unsigned int). В 64-битном режиме типы
size_t и unsigned int не совпадают. Тип size_t становится 64-битным, а тип unsigned int по-
прежнему остается 32-битным. В результате компилятор не знает, какой функции foo() отдать
предпочтение.

Теперь рассмотрим пример предупреждения, выдаваемого компилятором Visual C++ при сборке
кода в 64-битном режиме:

CArray<char, char> v;

int len = v.GetSize();

warning C4244: 'initializing' : conversion from 'INT_PTR' to 'int',

                      possible loss of data

Функция GetSize() возвращает тип INT_PTR, который совпадает с типом int в 32-битном коде. В 64-
битном коде тип INT_PTR имеет размер 64 бита, и происходит неявное приведение этого типа к
32-битному типу int. При этом теряются значения старших битов, о чем и предупреждает
компилятор. Неявное приведение типа может привести к ошибке, если количество элементов в
массиве превысит INT_MAX. Для устранения предупреждения и потенциальной ошибки следует
использовать для переменной "len" тип INT_PTR или ptrdiff_t.

Не торопитесь исправлять предупреждения до того, как познакомитесь с паттернами 64-битных
ошибок. Вы можете случайно, не исправив ошибку, замаскировать ее и тем самым сделать ее
обнаружение в дальнейшем более сложной задачей. О паттернах 64-битных ошибок, методах их
обнаружения и исправления вы сможете познакомиться в последующих уроках. Также вы можете
обратиться к следующим статьям: "20 ловушек переноса Си++ - кода на 64-битную платформу",
"64-битный конь, который умеет считать".


Типы size_t и ptrdiff_t
Поскольку большинство ошибок и предупреждений на этапе компиляции будет связано с
несовместимостью типов данных, рассмотрим два типа size_t и ptrdiff_t представляющих для нас
наибольший интерес с точки зрения создания 64-битного кода. Если вы используете компилятор
Visual C++, то эти типы являются для него встроенными, и подключения библиотечных файлов не
требуется. Если вы используете GCC, то вам потребуется использовать заголовочный файл
stddef.h.

size_t - базовый беззнаковый целочисленный тип языка Си/Си++. Является типом результата,
возвращаемого оператором sizeof. Размер типа выбирается таким образом, чтобы в него можно
было записать максимальный размер теоретически возможного массива любого типа. Например,
на 32-битной системе size_t будет занимать 32 бита, на 64-битной - 64 бита. Другими словами в
переменную типа size_t может быть безопасно помещен указатель. Исключение составляют
указатели на функции классов, но это особый случай. Тип size_t обычно применяется для
счетчиков циклов, индексации массивов, хранения размеров, адресной арифметики. Аналогами
данному типу являются: SIZE_T, DWORD_PTR, WPARAM, ULONG_PTR. Хотя в size_t можно помещать
указатель, для этих целей лучше подходит другой беззнаковый целочисленный тип uintptr_t, само
название которого отражает эту возможность. Типы size_t и uintptr_t являются синонимами.

ptrdiff_t - базовый знаковый целочисленный тип языка Си/Си++. Размер типа выбирается таким
образом, чтобы в него можно было записать максимальный размер теоретически возможного
массива любого типа. На 32-битной системе ptrdiff_t будет занимать 32 бита, на 64-битной - 64
бита. Как и в size_t в переменную типа ptrdiff_t может быть безопасно помещен указатель, за
исключением указателя на функцию класса. Также ptrdiff_t является результатом выражения, где
один указатель вычитается из другого (ptr1-ptr2). Тип ptrdiff_t обычно применяется для счетчиков
циклов, индексации массивов, хранения размеров, адресной арифметики. Аналогами данному
типу являются: SSIZE_T, LPARAM, INT_PTR, LONG_PTR. У типа ptrdiff_t есть синоним intptr_t,
название которого лучше отражает, что тип может хранить в себе указатель.

Типы size_t и ptrdiff_t были созданы для того, чтобы осуществлять корректную адресную
арифметику. Долгое время было принято считать, что размер int совпадает с размером
машинного слова (разрядностью процессора), и его можно использовать в качестве индексов, для
хранения размеров объектов или указателей. Соответственно адресная арифметика также
строилась с использованием типов int и unsigned. Тип int используется в большинстве обучающих
материалов по программированию на Си и Си++ в телах циклов и в качестве индексов.
Практически каноническим является код:

for (int i = 0; i < n; i++)

  a[i] = 0;

С развитием процессоров и ростом их разрядности стало нерационально дальнейшее увеличение
размерностей типа int. Причин для этого много: экономия используемой памяти, максимальная
совместимость и так далее. В результате появилось несколько моделей данных, описывающих
соотношение размеров базовых типов языков Си и Си++. Соответственно, не так просто стало
выбрать тип переменной для хранения указателя или размера объекта. Чтобы наиболее красиво
решить эту проблему и появились типы size_t и ptrdiff_t. Они гарантированно могут
использоваться для адресной арифметики. Теперь каноническим должен стать следующий код:

for (ptrdiff_t i = 0; i < n; i++)

  a[i] = 0;

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

Описанные типы size_t и ptrdiff_t можно назвать memsize-типами. Термин "memsize" возник, как
попытка лаконично назвать все типы, которые способны хранить в себе размер указателей и
индексов самых больших массивов. Под memsize-типом следует понимать все простые типы
данных языка Си/Си++, которые на 32-битой архитектуре имеют размер 32-бита, а на 64-битной
архитектуре - 64-бита. Примеры memsize-типов: size_t, ptrdiff_t, указатели, SIZE_T, LPARAM.

Авторы курса: Андрей Карпов (karpov@viva64.com), Евгений Рыжков (evg@viva64.com).
Правообладателем курса "Уроки разработки 64-битных приложений на языке Си/Си++"
является ООО "Системы программной верификации". Компания занимается разработкой
программного обеспечения в области анализа исходного кода программ. Сайт компании:
http://www.viva64.com.

Контактная информация: e-mail: support@viva64.com, 300027, г. Тула, а/я 1800.

More Related Content

PDF
Что такое size_t и ptrdiff_t
PDF
Разработка статического анализатора кода для обнаружения ошибок переноса прог...
PDF
20 ловушек переноса Си++ - кода на 64-битную платформу
PDF
Урок 13. Паттерн 5. Адресная арифметика
PDF
Урок 26. Оптимизация 64-битных программ
PDF
Особенности разработки 64-битных приложений
PDF
Сравнение диагностических возможностей анализаторов при проверке 64-битного кода
PDF
Урок 17. Паттерн 9. Смешанная арифметика
Что такое size_t и ptrdiff_t
Разработка статического анализатора кода для обнаружения ошибок переноса прог...
20 ловушек переноса Си++ - кода на 64-битную платформу
Урок 13. Паттерн 5. Адресная арифметика
Урок 26. Оптимизация 64-битных программ
Особенности разработки 64-битных приложений
Сравнение диагностических возможностей анализаторов при проверке 64-битного кода
Урок 17. Паттерн 9. Смешанная арифметика

What's hot (10)

PDF
Урок 15. Паттерн 7. Упаковка указателей
PDF
Статический анализ Си++ кода и новый стандарт языка C++0x
PDF
Урок 11. Паттерн 3. Операции сдвига
PDF
Правила статического анализа кода для диагностики потенциально опасных констр...
PDF
Урок 9. Паттерн 1. Магические числа
PDF
Урок 16. Паттерн 8. Memsize-типы в объединениях
PDF
Безопасность 64-битного кода
PDF
Как стандарт C++0x поможет в борьбе с 64-битными ошибками
PDF
64-битный конь, который умеет считать
PDF
Коллекция примеров 64-битных ошибок в реальных программах
Урок 15. Паттерн 7. Упаковка указателей
Статический анализ Си++ кода и новый стандарт языка C++0x
Урок 11. Паттерн 3. Операции сдвига
Правила статического анализа кода для диагностики потенциально опасных констр...
Урок 9. Паттерн 1. Магические числа
Урок 16. Паттерн 8. Memsize-типы в объединениях
Безопасность 64-битного кода
Как стандарт C++0x поможет в борьбе с 64-битными ошибками
64-битный конь, который умеет считать
Коллекция примеров 64-битных ошибок в реальных программах
Ad

Viewers also liked (20)

PDF
XLS
00 Paesita 2008 Resultados Por Centro Y SeccióN Sonsonate
PDF
Thift Shop Insights
PDF
Y Prime - CTMS
PDF
Presentation VoiceInstant
PPTX
PPT
Francisco chiluisa
PPTX
Presentación trabajo fina
PPSX
Realtor 360
PDF
Mongo DB Hackday Apr 28 2012
PPTX
E business e-market actualizado
PPT
Aprendizaje Cooperativo 22453 27667
PPTX
ESA - Qué es? Objetivos
PDF
Agenda de Comercio Exterior: Informe 2010-Perspectivas 2011.
PDF
Presentación del contador Envir durante la Feria Genera en Madrid
PDF
Above theclouds
DOCX
PDF
Vale Security Conference - 2011 - 13 - Nelson Brito
PDF
Akademy es2010 ideal_library_rafael_fernandez
PPTX
S&A Compañia
00 Paesita 2008 Resultados Por Centro Y SeccióN Sonsonate
Thift Shop Insights
Y Prime - CTMS
Presentation VoiceInstant
Francisco chiluisa
Presentación trabajo fina
Realtor 360
Mongo DB Hackday Apr 28 2012
E business e-market actualizado
Aprendizaje Cooperativo 22453 27667
ESA - Qué es? Objetivos
Agenda de Comercio Exterior: Informe 2010-Perspectivas 2011.
Presentación del contador Envir durante la Feria Genera en Madrid
Above theclouds
Vale Security Conference - 2011 - 13 - Nelson Brito
Akademy es2010 ideal_library_rafael_fernandez
S&A Compañia
Ad

Similar to Урок 5. Сборка 64-битного приложения (20)

PPTX
Паттерны 64-битных ошибок в играх
PDF
Забытые проблемы разработки 64-битных программ
PDF
Урок 10. Паттерн 2. Функции с переменным количеством аргументов
PDF
Урок 19. Паттерн 11. Сериализация и обмен данными
PDF
Урок 24. Фантомные ошибки
PDF
Большой брат помогает тебе
PPTX
C language lect_05_introduction
PDF
Статический анализ кода для верификации 64-битных приложений
PDF
Поиск явного приведения указателя к 32-битному типу
PDF
Урок 6. Ошибки в 64-битном коде
PDF
Красивая 64-битная ошибка на языке Си
ODP
C language. Introduction
PPTX
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++
PDF
Проблемы 64-битного кода на примерах
PPTX
PVS-Studio, решение для разработки современных ресурсоемких приложений
PDF
64-битная версия Loki
PPTX
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
PDF
Андрей Карпов, Приватные байки от разработчиков анализатора кода
PPTX
Принципы работы статического анализатора кода PVS-Studio
PPTX
На что нужно обратить внимание при обзоре кода разрабатываемой библиотеки
Паттерны 64-битных ошибок в играх
Забытые проблемы разработки 64-битных программ
Урок 10. Паттерн 2. Функции с переменным количеством аргументов
Урок 19. Паттерн 11. Сериализация и обмен данными
Урок 24. Фантомные ошибки
Большой брат помогает тебе
C language lect_05_introduction
Статический анализ кода для верификации 64-битных приложений
Поиск явного приведения указателя к 32-битному типу
Урок 6. Ошибки в 64-битном коде
Красивая 64-битная ошибка на языке Си
C language. Introduction
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++
Проблемы 64-битного кода на примерах
PVS-Studio, решение для разработки современных ресурсоемких приложений
64-битная версия Loki
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Андрей Карпов, Приватные байки от разработчиков анализатора кода
Принципы работы статического анализатора кода PVS-Studio
На что нужно обратить внимание при обзоре кода разрабатываемой библиотеки

More from Tatyanazaxarova (18)

PDF
Урок 27. Особенности создания инсталляторов для 64-битного окружения
PDF
Урок 25. Практическое знакомство с паттернами 64-битных ошибок
PDF
Урок 23. Паттерн 15. Рост размеров структур
PDF
Урок 21. Паттерн 13. Выравнивание данных
PDF
Урок 20. Паттерн 12. Исключения
PDF
Урок 8. Статический анализ для выявления 64-битных ошибок
PDF
Урок 7. Проблемы выявления 64-битных ошибок
PDF
Урок 4. Создание 64-битной конфигурации
PPTX
Статический анализ Си++ кода
PDF
PVS-Studio
PDF
PVS-Studio научился следить за тем, как вы программируете
PDF
Пояснения к статье про Copy-Paste
PDF
Использование анализатора PVS-Studio в процессе инкрементальной сборки в Micr...
PDF
Статический анализ и ROI
PDF
Вечный вопрос измерения времени
PDF
По колено в Си++ г... коде
PDF
Статический анализ и регулярные выражения
PDF
Трепещи, мир! Мы выпустили PVS-Studio 4.00 с бесплатным анализатором общего н...
Урок 27. Особенности создания инсталляторов для 64-битного окружения
Урок 25. Практическое знакомство с паттернами 64-битных ошибок
Урок 23. Паттерн 15. Рост размеров структур
Урок 21. Паттерн 13. Выравнивание данных
Урок 20. Паттерн 12. Исключения
Урок 8. Статический анализ для выявления 64-битных ошибок
Урок 7. Проблемы выявления 64-битных ошибок
Урок 4. Создание 64-битной конфигурации
Статический анализ Си++ кода
PVS-Studio
PVS-Studio научился следить за тем, как вы программируете
Пояснения к статье про Copy-Paste
Использование анализатора PVS-Studio в процессе инкрементальной сборки в Micr...
Статический анализ и ROI
Вечный вопрос измерения времени
По колено в Си++ г... коде
Статический анализ и регулярные выражения
Трепещи, мир! Мы выпустили PVS-Studio 4.00 с бесплатным анализатором общего н...

Урок 5. Сборка 64-битного приложения

  • 1. Урок 5. Сборка 64-битного приложения Хочется сразу предупредить читателя, что невозможно всесторонне описать процесс сборки 64- битного приложения. Настройки любого проекта достаточно уникальны, поэтому к адаптации настроек для 64-битной системы всегда надо подходить внимательно. В уроке будут описаны только общие шаги, которые важны для любого проекта. Эти шаги подскажут вам с чего начать процесс. Библиотеки Прежде чем попытаться собрать ваше 64-битное приложение, проверьте, что установлены все необходимые версии 64-битных библиотек и к ним корректно прописаны пути. Например, 32- битные и 64-битные библиотечные lib файлы отличаются и, как правило, находятся в различных каталогах. Исправьте найденные недочеты. Примечание. Если библиотеки представлены в исходных кодах, то должна присутствовать 64- битная конфигурация проекта. Учтите, что самостоятельно занимаясь модернизацией библиотеки для сборки ее 64-битной версии, вы можете нарушить лицензионные соглашения. Ассемблер Visual C++ не поддерживает 64-битный встроенный ассемблер. Вы должны использовать или внешний 64-битный ассемблер (например, MASM), или иметь реализацию той же функциональности на языке Си/Си++. Примеры ошибок и предупреждений при компиляции Начав сборку проекта, вы обнаружите большое количество ошибок компиляции и предупреждений, связанных с явным и неявным приведением типов. Продемонстрируем пример возникновения одной из ошибок. Пусть мы имеем код: void foo(unsigned char) {} void foo(unsigned int) {} void a(const char *str) { foo(strlen(str)); } Данный код успешно компилируется в 32-битном режиме. А в 64-битном компилятор Visual C++ выдаст сообщение: error C2668: 'foo' : ambiguous call to overloaded function
  • 2. .xxxx.cpp(16): could be 'void foo(unsigned int)' .xxxx.cpp(15): or 'void foo(unsigned char)' while trying to match the argument list '(size_t)' Функция strlen() возвращает тип size_t. На 32-битной системе тип size_t совпадает с типом unsigned int и компилятор выбирает для вызова функцию void foo(unsigned int). В 64-битном режиме типы size_t и unsigned int не совпадают. Тип size_t становится 64-битным, а тип unsigned int по- прежнему остается 32-битным. В результате компилятор не знает, какой функции foo() отдать предпочтение. Теперь рассмотрим пример предупреждения, выдаваемого компилятором Visual C++ при сборке кода в 64-битном режиме: CArray<char, char> v; int len = v.GetSize(); warning C4244: 'initializing' : conversion from 'INT_PTR' to 'int', possible loss of data Функция GetSize() возвращает тип INT_PTR, который совпадает с типом int в 32-битном коде. В 64- битном коде тип INT_PTR имеет размер 64 бита, и происходит неявное приведение этого типа к 32-битному типу int. При этом теряются значения старших битов, о чем и предупреждает компилятор. Неявное приведение типа может привести к ошибке, если количество элементов в массиве превысит INT_MAX. Для устранения предупреждения и потенциальной ошибки следует использовать для переменной "len" тип INT_PTR или ptrdiff_t. Не торопитесь исправлять предупреждения до того, как познакомитесь с паттернами 64-битных ошибок. Вы можете случайно, не исправив ошибку, замаскировать ее и тем самым сделать ее обнаружение в дальнейшем более сложной задачей. О паттернах 64-битных ошибок, методах их обнаружения и исправления вы сможете познакомиться в последующих уроках. Также вы можете обратиться к следующим статьям: "20 ловушек переноса Си++ - кода на 64-битную платформу", "64-битный конь, который умеет считать". Типы size_t и ptrdiff_t Поскольку большинство ошибок и предупреждений на этапе компиляции будет связано с несовместимостью типов данных, рассмотрим два типа size_t и ptrdiff_t представляющих для нас наибольший интерес с точки зрения создания 64-битного кода. Если вы используете компилятор Visual C++, то эти типы являются для него встроенными, и подключения библиотечных файлов не требуется. Если вы используете GCC, то вам потребуется использовать заголовочный файл stddef.h. size_t - базовый беззнаковый целочисленный тип языка Си/Си++. Является типом результата, возвращаемого оператором sizeof. Размер типа выбирается таким образом, чтобы в него можно было записать максимальный размер теоретически возможного массива любого типа. Например, на 32-битной системе size_t будет занимать 32 бита, на 64-битной - 64 бита. Другими словами в переменную типа size_t может быть безопасно помещен указатель. Исключение составляют
  • 3. указатели на функции классов, но это особый случай. Тип size_t обычно применяется для счетчиков циклов, индексации массивов, хранения размеров, адресной арифметики. Аналогами данному типу являются: SIZE_T, DWORD_PTR, WPARAM, ULONG_PTR. Хотя в size_t можно помещать указатель, для этих целей лучше подходит другой беззнаковый целочисленный тип uintptr_t, само название которого отражает эту возможность. Типы size_t и uintptr_t являются синонимами. ptrdiff_t - базовый знаковый целочисленный тип языка Си/Си++. Размер типа выбирается таким образом, чтобы в него можно было записать максимальный размер теоретически возможного массива любого типа. На 32-битной системе ptrdiff_t будет занимать 32 бита, на 64-битной - 64 бита. Как и в size_t в переменную типа ptrdiff_t может быть безопасно помещен указатель, за исключением указателя на функцию класса. Также ptrdiff_t является результатом выражения, где один указатель вычитается из другого (ptr1-ptr2). Тип ptrdiff_t обычно применяется для счетчиков циклов, индексации массивов, хранения размеров, адресной арифметики. Аналогами данному типу являются: SSIZE_T, LPARAM, INT_PTR, LONG_PTR. У типа ptrdiff_t есть синоним intptr_t, название которого лучше отражает, что тип может хранить в себе указатель. Типы size_t и ptrdiff_t были созданы для того, чтобы осуществлять корректную адресную арифметику. Долгое время было принято считать, что размер int совпадает с размером машинного слова (разрядностью процессора), и его можно использовать в качестве индексов, для хранения размеров объектов или указателей. Соответственно адресная арифметика также строилась с использованием типов int и unsigned. Тип int используется в большинстве обучающих материалов по программированию на Си и Си++ в телах циклов и в качестве индексов. Практически каноническим является код: for (int i = 0; i < n; i++) a[i] = 0; С развитием процессоров и ростом их разрядности стало нерационально дальнейшее увеличение размерностей типа int. Причин для этого много: экономия используемой памяти, максимальная совместимость и так далее. В результате появилось несколько моделей данных, описывающих соотношение размеров базовых типов языков Си и Си++. Соответственно, не так просто стало выбрать тип переменной для хранения указателя или размера объекта. Чтобы наиболее красиво решить эту проблему и появились типы size_t и ptrdiff_t. Они гарантированно могут использоваться для адресной арифметики. Теперь каноническим должен стать следующий код: for (ptrdiff_t i = 0; i < n; i++) a[i] = 0; Именно он может обеспечить надежность, переносимость, быстродействие. Почему - станет ясно из дальнейших уроков. Описанные типы size_t и ptrdiff_t можно назвать memsize-типами. Термин "memsize" возник, как попытка лаконично назвать все типы, которые способны хранить в себе размер указателей и индексов самых больших массивов. Под memsize-типом следует понимать все простые типы данных языка Си/Си++, которые на 32-битой архитектуре имеют размер 32-бита, а на 64-битной архитектуре - 64-бита. Примеры memsize-типов: size_t, ptrdiff_t, указатели, SIZE_T, LPARAM. Авторы курса: Андрей Карпов (karpov@viva64.com), Евгений Рыжков (evg@viva64.com).
  • 4. Правообладателем курса "Уроки разработки 64-битных приложений на языке Си/Си++" является ООО "Системы программной верификации". Компания занимается разработкой программного обеспечения в области анализа исходного кода программ. Сайт компании: http://www.viva64.com. Контактная информация: e-mail: support@viva64.com, 300027, г. Тула, а/я 1800.