Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
Другие темы раздела
C++ Почему С++ хороший для gamedeva? https://www.cyberforum.ru/ cpp/ thread607453.html
На всех сайтах, форумах пишут, что игры нужно писать на С/С++, но почему? Нигде не видел объяснения этому, может кто здесь объяснит?
C++ std::filesystem && std::asio и пр
Пытался найти хоть какие-то сроки включения всего этого в стандарт (так же ожидается lexical_cast, any, string_algo и т.д.) и вообщем везде написано разное, проскакивает инфа о 2017 годе... Как-то не слишком оптимистично, кто-то может подсказать какие-либо сведения по этому поводу (желательно с пруф линками)?
C++ Нажатие ЛКМ в экранных координатах https://www.cyberforum.ru/ cpp/ thread606849.html
Программа должна создавать точку в центре экрана(пусть не в центре(по указанным пикселям) эта точка должна присутствовать все время на экране,пока не будет выключена программа,при том при запущенных посторонних программах) и должна автоматически нажимать ЛКМ при появлении в квадрате(точки также должны указываться в пикселях). Это реально?Простите за корявое оформление и если не так тему...
C++ Где найти ответы к самоконтролю в книге Шилдта "С++ руководство для начинающих" https://www.cyberforum.ru/ cpp/ thread604817.html
В книге сказано,что ответы есть на сайте осборне ком, но он перенаправляет на другой сайт,на котором ничего нет кроме продажи книг,по крайней мере мне так показалось.
Автоматическое объявление объекта произвольного типа C++
Помогите найти информацию по "Автоматическому объявлению объекта произвольного типа". Что это такое, как работает и т.д.
C++ Как реализован unordered_map? https://www.cyberforum.ru/ cpp/ thread602581.html
Собственно, интересна именно практическая сторона вопроса, как реализуется идеальное хеширование за O(1) в среднем ясно, об этом можно почитать в том же Кормене. Понятно, что реализации в каждом компиляторе могут быть разными. Мне интересно, как это вообще можно написать. Если кто знает - расскажите, пожалуйста.
C++ Как интегрировать Notepad++ с MinGW компилятором? Уважаемые форумчане, подскажите как можно грамотно интегрировать Notepad++ (или аналогичный редактор с подcветкой разных синтаксисов) с MinGW компилятором (или опять же аналогичным по windows). https://www.cyberforum.ru/ cpp/ thread602226.html C++ На каком с++ лучше начать писать?
Здравствуйте. Я не особо разбираюсь в с++. Но написав одну из своих первых программ на C++/cli столкнулся с крешами из-за фреймврока на другой ОС. Сразу возникло подозрение что надо было писать на чистом c++ с использованием win api(но я не имею представления, как например использовать элемент activex в такой программе). Возможно мой вопрос покажется Вам некорректным и косноязычным, но я хочу...
C++ WideCharToMultiByte и std::string Легален ли такой код? На мой взгляд, все правильно, но программа в 3 случаях из 1000 портит память, если в коде есть эта функция. std::string tomb(const std::wstring &str, size_t code_page) { int cnt = WideCharToMultiByte((UINT)code_page, NULL, str.c_str(), -1, 0, 0, NULL, NULL); if(!cnt) return std::string(); std::string f(cnt); https://www.cyberforum.ru/ cpp/ thread600926.html C++ Нужен учебник https://www.cyberforum.ru/ cpp/ thread598633.html
Всем добрый день или вечер! Не могли бы вы мне посоветовать учебник для создания web-программ...программа должна работать с определённым сайтом.
C++ Реестр: как считать QWORD в DWORD64
Доброго времени суток! Ни в какую не выходит считать параметр реестра, в котором содержится число. хочу считать его именно как число, а не как стоку, со строками проблем не было, все работало так: char mainboard; if(RegOpenKeyExA(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System\\BIOS",0,KEY_QUERY_VALUE,&hKey)==ERROR_SUCCESS) { RegQueryValueEx(hKey, "BaseBoardProduct", NULL, NULL,...
C++ PROCESS_MEMORY_COUNTERS: какие поля отвечают за занимаемую оперативную и динамическую память помогите разобраться со структурой PROCESS_MEMORY_COUNTERS typedef struct _PROCESS_MEMORY_COUNTERS { DWORD cb; DWORD PageFaultCount; SIZE_T PeakWorkingSetSize; SIZE_T WorkingSetSize; SIZE_T QuotaPeakPagedPoolUsage; SIZE_T QuotaPagedPoolUsage; SIZE_T QuotaPeakNonPagedPoolUsage; https://www.cyberforum.ru/ cpp/ thread595338.html
Evg
Эксперт CАвтор FAQ
21280 / 8304 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
19.06.2012, 13:24  [ТС] 0

Процесс компиляции - C++ - Ответ 3183867

19.06.2012, 13:24. Показов 18223. Ответов 19
Метки (Все метки)

Лучший ответ Сообщение было отмечено как решение

Решение

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

Рассмотрим на простеньком примере

C
#include <stdio.h>
 
int main (void)
{
  printf ("Hello world\n");
  return 0;
}
Конкретные действия буду объяснять на примере компилятора gcc. Просто потому, что с ним я умею работать из консоли. Наверняка все эти действия можно выполнять и из-под IDE, но я с ними не работаю, а потому не знаю, как это делается

*** UPDATE ***
Пока писал, понял, что пример выбрал неудачно и методику изложения следует немного поменять. Но для этого нужно в очередной раз найти время и уже в законченном виде с нормальными пояснениями выложить в блог, где можно спокойно редактировать и исправлять

1 этап. Препроцессирование

На данном этапе работа идёт только с текстовыми файлами. Здесь препроцессор объединит наш исходник и все include-файлы в один большой текстовый файл. Для нашего случая это будет что-то типа:

C
/* Здесь идут потроха, подцепившиеся из stdio.h и прочих .h файлов,
 * которые могут подключаться внутри stdio.h. Касаемо функций или переменных
 * тут будут только описания, но никаких определений */
 
...
 
extern int printf (const char*, ...);
 
...
 
 
/* Текст из stdio.h закончился, далее идёт текст нашей программы */
 
int main (void)
{
  printf ("Hello world\n");
  return 0;
}
Во время работы препроцессора идёт работа со всякими внешними файлами (include'ами) и путями (каталоги, в которых компилятор ищет include-файлы)

Результат работы препроцессора можно посмотреть так:

Bash
$ gcc t.c -E -o t.i
Итоговый препроцессированный текст будет в файле t.i

2 этап. Трансляция

Полученный после препроцессирования единый текстовый файл скармливается транслятору. В процессе работы транслятора уже нет никакой работы со внешними файлами, путями поиска и т.п. На вход транслятору подаётся один файл с исходником, на выходе транслятора получается один файл, содержащий ассемблерный текст. А сам транслятор занимается преобразованием исходника на языке программирования в ассемблерный текст, содержащий код целевой машины на языке ассемблера.

В нашем случае на выходе транслятора мы получим ассемблерный текст. Я привожу тот текст, который получен в результате работы компилятора gcc. Некоторые интересные места я отметил стрелочками и пронумеровал. О них пойдёт речь ниже.

Assembler
    .file   "t.c"
    .section    .rodata.str1.1,"aMS",@progbits,1
.LC0:                          <----- 1
    .string "Hello world\n"
    .text
    .p2align 4,,15
.globl main                    <----- 2
    .type   main, @function
main:                          <----- 3
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $16, %esp
    movl    $.LC0, 4(%esp)     <----- 4
    call    printf             <----- 5
    xorl    %eax, %eax
    leave
    ret
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
    .section    .note.GNU-stack,"",@progbits
Ассемблерный текст является не просто образом будущего кода, но ещё и образом будущего объектного файла, в котором будут символьные имена меток, которые в свою очередь будут использоваться при линковке.

В нашем случае мы видим, что в коде имеются две метки. Метка ".LC0" (стрелка 1), описывающая набор символов от строкового литерала и метка "main" (стрелка 3), описывающая начало функции main. У каждой метки есть так называемая область видимости: локальная или глобальная. Локальные метки видны только внутри данного модуля, глобальные метки видны из других модулей. Метка ".LC0" является локальной, т.к. строковой литерал - это внутренние данные нашего модуля. Метка main является глобальной, т.к. эта функция должна быть видна извне (в исходнике у main'а нет модификатора static), а потому этот факт подсвечивается специальной директивой (стрелка 2).

Помимо вхождения меток мы видим ещё и обращения к меткам: обращение к строковому литералу ".LC0" (стрелка 4) и обращение к внешней метке "printf" (стрелка 5).

Результат работы препроцессора можно посмотреть так:

Bash
$ gcc t.c -S -o t.s
Итоговый ассемблерный текст будет в файле t.s

3 этап. Ассемблирование

Полученный ассемблерный текст далее передаётся программе-ассемблеру, которая преобразует его в объектный файл. Объектный файл представляет собой бинарные коды целевой машины плюс дополнительная информация о метках и их использовании. Информация, содержащаяся в объектном файле принципиально ничем не отличается от информации, содержащейся в ассемблерном тексте. Только весь код вместо мнемоник, понятных человеку, содержит двоичный код, понятный машине. А вместо меток, расставленных по ассемблерному тексту, объектный файл содержит специальную таблицу символов (symbol table), описывающую все метки из нашего ассемблерного текста и таблицу перемещений (relocations table), описывающую точки, где метки использовались. Эти таблицы спроектированы таким образом, чтобы с ними было удобно работать линкеру и дизассемблеру.

Конкретно в нашем случае эти таблицы будут выглядеть примерно таким образом. В объектном файле определена локальная метка ".LC0", глобальная метка "main" и внешняя метка "printf", к которой в данном файле есть обращения (но определения метки нет). В объектном файле есть использование метки ".LC0" и использования метки "printf"

Важным моментом является то, что в объектном файле адреса ещё не настроены. Например, у нас в функции main есть обращение к метке ".LC0". но в том месте кода, где происходит это обращение, адрес метки ".LC0" ещё не проставлен, т.к. он будет известен только на этапе линковки

Объектный файл можно получить так:

Bash
$ gcc t.c -c -o t.o
В итоге создастся объектный файл с именем t.o. Просто так в него заглянуть уже не получится, т.к. это бинарный файл, но при помощи воспомогательных утилит можно выудить любую информацию.

Таблица символов (меток) - symbol table:

Bash
$ readelf --symbols t.o
 
Symbol table '.symtab' contains 10 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
...
     8: 00000000    41 FUNC    GLOBAL DEFAULT    1 main
     9: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND printf
Здесь удалил целую портянку служебных фиктивных символов, о которых на данном этапе можно и не вспоминать. Обратите внимание, что среди таблицы символов отсутствует метка ".LC0". Для процесса линковки метка как таковая не нужна (ибо она локальная внутри модуля), а все обращения к метке ассемблер заменил на смещения внутри объектного файла (см. далее). Это некая оптимизация. При желании можно попросить ассемблер эту метку сохранить (но это надо почитать документацию)

Таблица перемещений (использований) - relocation table:

Bash
$ readelf --relocs t.o
 
Relocation section '.rel.text' at offset 0x360 contains 2 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00000015  00000501 R_386_32          00000000   .rodata.str1.1    <-----
00000021  00000902 R_386_PC32        00000000   printf
Место, помеченное стрелкой - это есть обращение к метке ".LC0", которое ассемблер заменил на обращение к секции данных с заданным смещением (правда для данного примера смещение оказалось нулевым)

4 этап. Линковка

Полученный объектный файл (а их может быть несколько) отдаётся линкеру. Линкер склеивает между собой все поданные ему файлы и формирует один большой исполняемый файл. Помимо объектных файлов компилятор подаёт в линкер ещё и библиотеки. Какие-то библиотеки компилятор подаёт невидимым для пользователя образом (т.е. пользователь непосредственно в этом процессе не участвует). Какие-то библиотеки пользователь сам просит компилятор передать линкеру. В первую группу, как правило, относятся библиотеки, отвечающие за run-time поддержку языка программирования и библиотеки, входящие в состав стандарта языка программирования или входящие в состав стандартной библиотечной поддержки на данной операционной системе. Библиотека, содержащая реализацию функции printf относится именно к этой группе. Ко второй группе относятся все пользовательские библиотеки (графические библиотеки, библиотеки для работы с криптографией и прочее)

В контексте данной статьи к библиотекам нужно относиться следующим образом. Где-то кто-то написал реализации всех стандартных функций, в том числе и printf. Далее все эти реализации откомпилированы до объектного файла. Дальше каким-то образом склеили эти объектные файлы в единый файл (или в небольшое количество раздельных файлов) и назвали эти файлы словом "библиотека". Т.е. библиотека - это набор уже откомпилированных кодов. Далее эту библиотеку и include-файлы к ним включили в состав компилятора или в состав операционной системы

Помимо склеивания файлов линкер ещё и занимается настройкой адресов. Поскольку весь набор кодов, требуемых для формирования программы-бинарника, уже имеется на руках у линкера, то линкер после склеивания уже однозначно может сказать, по какому адресу будет располагаться та или иная функция или переменная. Для каждого файла, поступившего на ликновку, линкер заглянет в таблицу перемещений (использований), из которой поймёт, в какое место кода какой адрес нужно прописать. Конкретно в нашем случае в объектном файле у нас две перемещения: для бывшей метки ".LC0" (которая превратилась в обращение к секции с данными) и для метки printf. В итоге в функцию main в те места, которые засвечены в таблице перемещений, будут воткнуты итоговые адреса в исполняемом файле, соответствующие местоположению метки ".LC0" и функции "printf"

================================================================

В общем, пояснение было несколько сумбурным, а потому лучше будет, если ты задашь конкретные вопросы по непонятным местам, чтобы было ясно, каким образом в дальнейшем аккуратно это дело переписать

Вернуться к обсуждению:
Процесс компиляции C++
45
Заказать работу у эксперта
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
19.06.2012, 13:24
Готовые ответы и решения:

Открыть процесс процесс на полный доступ, и запретить для других
Всем доброго времени суток. Друзья, HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE,...

Процесс A в цикле просит пользователя ввести 5 чисел и затем передает их процессу B. Процесс B отображает на
#include &lt;iostream&gt; #include &quot;windows.h&quot; using namespace std; int main() { int n; cin &gt;&gt;...

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

Есть процесс A и дочерний процесс B, который находит хэндл родительского процесса A. И этот хэндл в разных случаях РАЗНЫЙ! Почему?
Друзья! Вот код A.exe, суть которого просто стать родительским для B.exe и висеть в системе. ...

19
19.06.2012, 13:24
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.06.2012, 13:24
Помогаю со студенческими работами здесь

Процесс компиляции Java
Здравствуйте форумчане . Помогите разобраться в сборке Hello World'a. ...

Опишите пошагово процесс компиляции DLL
Есть игра Call of Duty. Умельцы создали для нее аддон. На основе этого аддона в игре можно...

Процесс компиляции aspx страниц на Web севере
Здравствуйте! Возник вопрос, может быть он покажется странным: Если исходники aspx...

Как автоматизировать процесс компиляции и компоновки файла asm?
Здравствуйте уважаемые. Меня интересует как можно автоматизировать процесс компиляции и компоновки...

0
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru