символ не найден AKA неопределенный символ - PullRequest
0 голосов
/ 29 апреля 2011

Большинство людей, работающих в UNIX, часто сталкиваются с этой раздражающей ошибкой. а иногда это займет меньше времени, а иногда - чертовски много времени.

Даже я сталкивался с этим регулярно, и мне нужен какой-нибудь хороший документ или статья о конкретной ошибке в c / c ++

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

Может ли кто-нибудь помочь мне узнать, что это за дела?

Ответы [ 4 ]

3 голосов
/ 29 апреля 2011

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

  • Вы объявили, но никогда не определяли его
  • Вы определили его, но не добавили скомпилированный символ (объектный файл / библиотека) к компоновщику
  • Он является внешним, и вы забыли связать библиотеку, либо вы ссылаетесь на неверную версию, либо в неправильном порядке.

Первый вариант немногохитрее, если вы намеревались определить символ, но не соответствовали объявлению (объявлено void foo( int, double );, но определено void foo( double, int ). Как и во всех других случаях, компилятор сообщит вам точную подпись, которую ищетдля, убедитесь, что вы определили , что символ , а не что-то близкое или похожее, может быть конкретным угловым случаем, если вы используете разные соглашения о вызовах в объявлении и определении, так как они будут выглядеть очень похожев коде.

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

Чтобы помочь вам определить, какие символы на самом деле определены, вы можете использовать nm (gcc, который распространен среди систем Unix).Таким образом, вы можете запустить nm для объектных файлов / библиотек, на которые вы ссылаетесь, и найти символ, на который жалуется компоновщик.Это поможет в тех случаях, когда порядок - это то, что имеет значение (т. Е. Символ есть, но компоновщик его пропустил).

Во время выполнения (спасибо Matthieu M. за указание на это) у вас могут быть похожиепроблемы с динамическими библиотеками, если в LD_LIBRARY_PATH найдена неправильная версия библиотеки, вы можете получить библиотеку, в которой нет необходимого символа.

2 голосов
/ 29 апреля 2011

Хотя они могут зависеть от платформы, у меня есть несколько «более сложных» примеров некоторых моментов от Андреаса и Дэвида:

  • При работе с общими библиотеками (.so или.dll) и связыванием с символами, которые не экспортируются (dllimport / dllexport в Windows и видимость («по умолчанию») с GCC в * nix)
  • Или аналогично: связывание со статической библиотекой при ожидании совместной библиотеки или наоборот. Это немного похоже на комментарий Матье о связывании с другой, неожиданной версией библиотеки.
  • Создание чисто виртуального класса и отсутствие предоставления реализации хотя бы для одного метода (в результате чего vtable недоступен).
  • На самом деле более сложный случай объявления, но не определения: ошибки компоновки, которые вы можете получить при работе с большими вложенными шаблонами. Выяснить, что не было определено, может быть сложно с большими сообщениями об ошибках.
1 голос
/ 29 апреля 2011

Я полагаю, вы ссылаетесь на ошибку компоновщика. Вот список из моей головы в том, что я считаю наиболее распространенным:

  • Вы забыли сообщить компоновщику о зависимости (например, LIB-файл).
  • У вас есть класс со статическим членом данных, и вы забыли его инициализировать (только C ++).
  • Вы объявили функцию не чисто виртуальной и забыли ее реализовать.
  • Вы забыли реализовать функцию, которую вы вызывали из другой функции (только C, C ++ выдаст ошибку компилятора, которую гораздо легче найти).
  • Вы объявили внешнюю переменную и забыли ее инициализировать.
  • Объявление функции не соответствует реализации (только C ++, C примет ее и может ужасно умереть).
  • Вы забыли реализовать функцию, которую вы объявили и вызвали из другой функции.
1 голос
/ 29 апреля 2011

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

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

Symbols

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

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

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

Надеюсь, что это помогло:)

Приветствия!

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