Не компилируется файл c

Обновлено: 07.07.2024

В данной статье я хочу рассказать о том, как происходит компиляция программ, написанных на языке C++, и описать каждый этап компиляции. Я не преследую цель рассказать обо всем подробно в деталях, а только дать общее видение. Также данная статья — это необходимое введение перед следующей статьей про статические и динамические библиотеки, так как процесс компиляции крайне важен для понимания перед дальнейшим повествованием о библиотеках.

Все действия будут производиться на Ubuntu версии 16.04.
Используя компилятор g++ версии:

Состав компилятора g++

Мы не будем вызывать данные компоненты напрямую, так как для того, чтобы работать с C++ кодом, требуются дополнительные библиотеки, позволив все необходимые подгрузки делать основному компоненту компилятора — g++.

Зачем нужно компилировать исходные файлы?

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

Этапы компиляции:

Перед тем, как приступать, давайте создадим исходный .cpp файл, с которым и будем работать в дальнейшем.

driver.cpp:

1) Препроцессинг

Самая первая стадия компиляции программы.

Получим препроцессированный код в выходной файл driver.ii (прошедшие через стадию препроцессинга C++ файлы имеют расширение .ii), используя флаг -E, который сообщает компилятору, что компилировать (об этом далее) файл не нужно, а только провести его препроцессинг:

Взглянув на тело функции main в новом сгенерированном файле, можно заметить, что макрос RETURN был заменен:

В новом сгенерированном файле также можно увидеть огромное количество новых строк, это различные библиотеки и хэдер iostream.

2) Компиляция

На данном шаге g++ выполняет свою главную задачу — компилирует, то есть преобразует полученный на прошлом шаге код без директив в ассемблерный код. Это промежуточный шаг между высокоуровневым языком и машинным (бинарным) кодом.

Ассемблерный код — это доступное для понимания человеком представление машинного кода.

Используя флаг -S, который сообщает компилятору остановиться после стадии компиляции, получим ассемблерный код в выходном файле driver.s:

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

3) Ассемблирование

Так как x86 процессоры исполняют команды на бинарном коде, необходимо перевести ассемблерный код в машинный с помощью ассемблера.

Ассемблер преобразовывает ассемблерный код в машинный код, сохраняя его в объектном файле.

Объектный файл — это созданный ассемблером промежуточный файл, хранящий кусок машинного кода. Этот кусок машинного кода, который еще не был связан вместе с другими кусками машинного кода в конечную выполняемую программу, называется объектным кодом.

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

Получим машинный код с помощью ассемблера (as) в выходной объектный файл driver.o:

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

4) Компоновка

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

Таблица символов — это структура данных, создаваемая самим компилятором и хранящаяся в самих объектных файлах. Таблица символов хранит имена переменных, функций, классов, объектов и т.д., где каждому идентификатору (символу) соотносится его тип, область видимости. Также таблица символов хранит адреса ссылок на данные и процедуры в других объектных файлах.
Именно с помощью таблицы символов и хранящихся в них ссылок линкер будет способен в дальнейшем построить связи между данными среди множества других объектных файлов и создать единый исполняемый файл из них.

Получим исполняемый файл driver:

5) Загрузка

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

Запустим нашу программу:

Заключение

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

В этой статье содержится разрешение устранения неполадок для компиляторов Visual C++ или Visual C++ Linker.

Применяется к: Microsoft Visual C++ 2010 Express, Visual Studio
Исходный номер КБ: 974229

Действие

При расследовании возможной проблемы с компилятором Microsoft Visual C++ или линкером важно получить как можно больше сведений о процессе сборки и используемых параметрах. В этой статье рассмотрены некоторые советы по устранению неполадок, которые помогут решить проблему сборки или получить всестороннюю информацию для службы поддержки Майкрософт.

Решение

Для проблем компилятора, таких как внутренние ошибки компилятора (т. е. C1001), зависает или сбои, может быть полезно захватить выход препроцессора C/C++ для предоставления упрощенного репродуцируемый пример проблемы. В Visual C++ IDE это можно сделать, задав свойство Generate Preprocessed File with Line Numbers (/P) или Without Line Numbers (/EP/P). Это свойство можно найти на страницах свойств проекта в параметрах Configuration Properties, C/C++, Preprocessor.

Этот параметр можно установить на уровне проекта из меню Project Properties, в этом случае оно будет создавать файлы для всех исходных файлов в проекте или его можно установить для одного файла, щелкнув правой кнопкой мыши файл в проводнике решений, выбрав контекстное меню Properties, чтобы привести диалоговое окно свойств для одного .i файла.

Переключатель компилятора /P направляет CL.EXE для захвата вывода препроцессора в файл. Добавление /EP подавляет добавление сведений о номере строки в итоговом файле. /P достаточно, но /EP/P создает меньший файл вывода. Созданный файл вывода препроцессора будет иметь то же имя, что и исходный файл, который компилирован, но с расширением файла a.i, например, file1.cpp создает файл вывода препроцессора file1.i в том же каталоге.

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

Вы можете самостоятельно компилировать файл вывода препроцессора вне контекста Visual Studio проекта. Файл содержит все сведения о файле загона, замене макроса и сведениях директивы компиляторов, необходимых для компиляции этого конкретного или .i .C .CPP исходных файлов. Другими словами, это автономный модуль, который должен иметь возможность воспроизводить проблему компиляции без каких-либо зависимостей от других файлов. В результате файл часто будет большим и содержит большое количество белого пространства.

Проблемы со ссылками

Для проблем со ссылками (ошибки типа LNKxxxxx) можно использовать командный переключатель командной строки /LINKREPRO для создания тестового случая, содержащего только входные данные ссылок без зависимости от исходных файлов. /LINKREPRO использует следующий синтаксис:

'<path>' это полный путь к пустой папке в локальной файловой системе. Эта папка уже должна существовать — ссылка не создаст ее автоматически и создаст ошибку, если папка не существует.

Этот параметр не подвергается непосредственному воздействию в проектной системе. Чтобы добавить его в сборку, откройте меню свойства проекта из Project меню. В конфигурации Свойства , Linker, Командная строка , в поле Дополнительные параметры изменить, введите переключатель (в том числе вперед слэш) и заменить путь с уже существующей локальной папки /LINKREPRO:<path> пути. Пример: /LINKREPRO:C:\TEMP\LINKREPRO\ .

Если в этом окне редактирования уже есть другие параметры линкера, разделяйте их запятой.

Кроме того, можно использовать переменную LINK_REPRO среды. Если переменная среды существует, линкатор будет читать выходной путь из переменной среды и LINK_REPRO создавать linkrepro. Переключатель /LINKREPRO не требуется при использовании LINK_REPRO переменной среды. Использование LINK_REPRO переменной среды:

Откройте командную Visual Studio командную подсказку. Это устанавливается в меню Пуск, в Visual Studio папке под Инструменты Visual Studio подмастерье.

Создайте LINK_REPRO переменную среды, указывающую на существующий и пустой каталог, например: SET LINK_REPRO=C:\TEMP\LINKREPRO\ .

Запустите Visual Studio из той же командной подсказки, чтобы она разделяет копию измененной среды.

Откройте проект и перестроим весь проект.

Когда LINK.EXE вызывается в сборке, она копирует все необходимое для привязки проекта к каталогу linkrepro. Среди скопированные файлы будут ваши объектные файлы (. OBJ), необходимые файлы библиотеки (. LIB), включая библиотеки Майкрософт и файл ответа linker (LINK. RSP), чтобы ССЫЛКА больше не зависела от файла решения.

Чтобы подтвердить, что у вас есть все необходимые файлы для воспроизведения проблемы ссылок, можно запустить LINK в каталоге, указанном переменной LINK_REPRO среды, используя файл ответа linker, созданный linkrepro: LINK @link.rsp .

Перед этим используйте следующую команду, чтобы отключить эту функцию при использовании переменной среды командной строки: SET LINK_REPRO= .

Этот процесс также можно использовать для проверки файлов, участвующих в создании библиотеки, при использовании LIB.EXE link/LIB.

Заявление об отказе от ответственности

Быстрый отказ от публикации

Статьи быстрого публикации предоставляют сведения непосредственно из организации поддержки Майкрософт. Сведения, содержащиеся в этом ниже, создаются в ответ на возникающие или уникальные темы или предназначены для дополнения других сведений базы знаний.

Заявление об отказе от ответственности

Корпорация Майкрософт и(или) ее поставщики не делают никаких представлений или гарантий относительно пригодности, надежности или точности сведений, содержащихся в документах и связанных с ними графиках, опубликованных на этом сайте ("материалы") для любых целей. Эти материалы могут включать технические неточности или опечатки и могут быть пересмотрены в любое время без уведомления.

В максимальной степени, разрешенной применимым законодательством, Корпорация Майкрософт и/или ее поставщики дисклеймировали и исключали все представления, гарантии и условия, будь то экспресс- или подразумеваемые или нормативные, включая представления, гарантии или условия названия, отсутствие нарушения, удовлетворительное состояние или качество, торговая доступность и пригодность для определенной цели, в отношении материалов.

Компилятору не удается найти объявление идентификатора. Эта ошибка имеет несколько возможных причин. Наиболее распространенными причинами C2065 является то, что идентификатор не был объявлен, идентификатор написан неправильно, заголовок, где объявляется идентификатор, не включается в файл, или в идентификаторе отсутствует квалификатор области, например, cout вместо std::cout . Дополнительные сведения об объявлениях в C++ см. в разделе объявления и определения (c++).

Ниже приведены некоторые распространенные проблемы и более подробные решения.

Идентификатор не объявлен

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

Если идентификатор является членом класса или структуры или объявлен в пространстве имен, он должен уточняться именем класса или структуры или именем пространства имен при использовании вне структуры, класса или области пространства имен. Кроме того, пространство имен должно быть помещено в область с помощью using директивы, такой как using namespace std; , или имя члена должно быть помещено в область с помощью using объявления, такого как using std::string; . В противном случае неполное имя считается необъявленным идентификатором в текущей области.

Если идентификатор является тегом для определяемого пользователем типа, например, class или struct , тип тега должен быть объявлен до его использования. Например, объявление struct SomeStruct < /*. */ >; должно существовать, прежде чем можно будет объявить переменную SomeStruct myStruct; в коде.

Если идентификатор является псевдонимом типа, тип должен быть объявлен с помощью using объявления или typedef перед тем, как его можно будет использовать. Например, необходимо объявить, using my_flags = std::ios_base::fmtflags; прежде чем можно будет использовать my_flags в качестве псевдонима типа для std::ios_base::fmtflags .

Пример: идентификатор с ошибками

Эта ошибка обычно возникает, когда имя идентификатора написано неправильно или идентификатор использует неправильные прописные и строчные буквы. Имя в объявлении должно точно совпадать с именем, которое вы используете.

Пример. Использование неограниченного идентификатора

Эта ошибка может возникать, если идентификатор не является правильно заданной областью. Если вы видите C2065 при использовании cout , это является причиной. Если функции и операторы стандартной библиотеки C++ не полностью определены в пространстве имен или вы не передали std пространство имен в текущую область с помощью using директивы, компилятор не сможет их найти. Чтобы устранить эту проблему, необходимо либо полностью определить имена идентификаторов, либо указать пространство имен с помощью using директивы.

Этот пример не компилируется cout , поскольку и endl определены в std пространстве имен:

Идентификаторы, объявляемые внутри class типов, struct или, enum class также должны уточняться именем их включающей области при их использовании за пределами этой области.

Пример: предварительно скомпилированный заголовок не является первым

Этот пример не компилируется cout , поскольку и endl определены в <iostream> заголовке, который игнорируется, поскольку он включается перед предкомпилированным файлом заголовка. Чтобы выполнить сборку этого примера, создайте все три файла, а затем скомпилируйте файл stdafx. cpp, а затем скомпилируйте C2065_pch. cpp.

Пример: отсутствует заголовочный файл

Вы не включили заголовочный файл, объявляющий идентификатор. Убедитесь, что файл, содержащий объявление идентификатора, включен в каждый исходный файл, который его использует.

Другая возможная причина заключается в том, что при использовании списка инициализаторов не включается <initializer_list> заголовок.

эта ошибка может возникать в исходных файлах Windows классических приложений, если вы определяете VC_EXTRALEAN , WIN32_LEAN_AND_MEAN или WIN32_EXTRA_LEAN . Эти макросы препроцессора исключают некоторые файлы заголовков из Windows. h и афксв _ W32. h для ускорения компиляции. Просмотрите Windows. h и afxv_w32. h, чтобы получить последние сведения о том, что исключено.

Пример: отсутствует закрывающая кавычка

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

Пример. Использование итератора вне области действия цикла

Эта ошибка может возникать, если объявить переменную-итератор в for цикле, а затем попробовать использовать эту переменную итератора вне области for цикла. Компилятор включает параметр компилятора /Zc: forScope по умолчанию. Дополнительные сведения см. в разделе Поддержка итераторов отладки .

Пример: объявление удаленного препроцессора

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

Это пример кода, который работает при сборке в отладке, но не в розницу:

Пример: сбой выведения типа C++/CLI

Эта ошибка может возникать при вызове универсальной функции, если аргумент предполагаемого типа не может быть выведен из используемых параметров. Дополнительные сведения см. в разделе универсальные функции (C++/CLI).

Пример: параметры атрибута C++/CLI

эта ошибка также может быть вызвана работой по согласованности компилятора, выполненной для Visual Studio 2005: проверка параметров для Visual C++ных атрибутов.


Я использую windows 8

  • 1 Действительно ли ваш исходный файл содержит эти кавычки?
  • Я не могу собрать воедино достаточно конкретных деталей из этого. Пожалуйста, используйте полные предложения с полными словами, заглавными буквами, дословным кодом . Ваш код и команды компиляции связаны с C, но вы отметили вопрос C ++. Что здесь происходит?
  • Дубликат? Dev C в Windows 8: внутренняя ошибка gcc
  • Можете попробовать сделать это вручную и подскажите, в чем ошибка? gcc -o hello hello.c (или как там называется ваш файл)

У меня была эта проблема, и я исправил ее, перейдя в: C: \ Dev-Cpp \ libexec \ gcc \ mingw32 \ 3.4.2, затем удалив collect2.exe

  • работал .. но зачем он там, если в нем нет необходимости?
  • О Боже. вам действительно не следует удалять двоичные файлы MinGW. он может многое испортить.
  • В качестве альтернативы, вместо удаления "collect2.exe", вы можете переименовать его, чтобы при необходимости можно было вернуть его исходное имя. Мир!

Установите новую версию Dev c ++. Он отлично работает в Windows 8. Он также поддерживает 64-битную версию.

  • 2 Со времен мрачных времен Bloodshed Dev-C ++ появился ряд улучшенных IDE. Qt Creator (даже для проектов, отличных от Qt!) Находится в верхней части моего списка, за ним следует хороший текстовый редактор + командная строка.

Я думаю, вы используете Windows 7 с Orwell Dev CPP

Эта версия Dev CPP подходит только для Windows 8. Однако в Windows 7 вам понадобится более старая версия, которая называется devcpp-4.9.9.2_setup.exe. Загрузите ее по ссылке и используйте. (Не забудьте удалить любую другую версию, уже установленную на вашем компьютере) Также обратите внимание, что более старая версия не работает с Windows 8.

Теперь вы увидите вкладку с и и соответствующий путь к ней. Измените путь и , чтобы использовать и соответственно. Теперь это будет работать.


Причина в том, что вы использовали компиляторы, созданные для Linux.

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

Я нашел решение. Пожалуйста, выполните следующие действия:

Щелкните правой кнопкой мыши на My comp. Икона

Щелкните Advanced Setting.

Щелкните переменную среды. В верхней части переменной среды нажмите New

Я столкнулся с той же проблемой, что и описанная выше.

Это можно решить, создав новый проект и новый файл в этом проекте. Сохраните файл, а затем попробуйте собрать и запустить.

Читайте также: