Ошибка средств компоновщика LNK2005

символ , уже определенный в объекте

Символ был определен несколько раз.

За этой ошибкой следует неустранимая ошибка LNK1169.

Возможные причины и способы устранения

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

Ниже приведены некоторые распространенные причины этой ошибки.

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

    // LNK2005_global.h
    int global_int;  // LNK2005
    

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

    • Объявите переменную extern в файле заголовка: extern int global_int;затем определите ее и при необходимости инициализировать ее в одном и только одном исходном файле: int global_int = 17; Эта переменная теперь является глобальной, которую можно использовать в любом исходном файле, объявив его extern, например, включив файл заголовка. Мы рекомендуем это решение для переменных, которые должны быть глобальными, но хорошая практика проектирования программного обеспечения сводит к минимуму глобальные переменные.

    • Объявите статическую переменную: static int static_int = 17;. Это ограничивает область определения текущим файлом объектов и позволяет нескольким файлам объектов иметь собственную копию переменной. Не рекомендуется определять статические переменные в файлах заголовков из-за возможности путаницы с глобальными переменными. Предпочитайте перемещать определения статических переменных в исходные файлы, которые используют их.

    • Объявите переменную selectany: __declspec(selectany) int global_int = 17;. Это сообщает компоновщику выбрать одно определение для использования всеми внешними ссылками и отсодействовать карта остальные. Это решение иногда полезно при объединении библиотек импорта. В противном случае мы не рекомендуем использовать его как способ избежать ошибок компоновщика.

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

    // LNK2005_func.h
    int sample_function(int k) { return 42 * (k % 167); }  // LNK2005
    

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

    • inline Добавьте ключевое слово в функцию:

      // LNK2005_func_inline.h
      inline int sample_function(int k) { return 42 * (k % 167); }
      
    • Удалите текст функции из файла заголовка и оставьте только объявление, а затем реализуйте функцию в одном и только одном исходном файле:

      // LNK2005_func_decl.h
      int sample_function(int);
      
      // LNK2005_func_impl.cpp
      int sample_function(int k) { return 42 * (k % 167); }
      
  • Эта ошибка также может возникать, если вы определяете функции-члены вне объявления класса в файле заголовка:

    // LNK2005_member_outside.h
    class Sample {
    public:
        int sample_function(int);
    };
    int Sample::sample_function(int k) { return 42 * (k % 167); }  // LNK2005
    

    Чтобы устранить эту проблему, переместите определения функции-члены внутри класса. Функции-члены, определенные внутри объявления класса, неявно встраиваются.

    // LNK2005_member_inline.h
    class Sample {
    public:
        int sample_function(int k) { return 42 * (k % 167); }
    };
    
  • Эта ошибка может возникать, если вы связываете несколько версий стандартной библиотеки или CRT. Например, если вы пытаетесь связать библиотеки CRT для розничной торговли и отладки, либо статических и динамических версий библиотеки или двух разных версий стандартной библиотеки с исполняемым файлом, эта ошибка может быть сообщена много раз. Чтобы устранить эту проблему, удалите все копии каждой библиотеки из команды ссылки. Мы не рекомендуем смешивать розничные и отладочные библиотеки или разные версии библиотеки в одном исполняемом файле.

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

  • Эта ошибка может возникать, если при использовании параметра /clr используется статические и динамические библиотеки. Например, эта ошибка может возникать, если вы создаете библиотеку DLL для использования в исполняемом файле, который связывается со статическим CRT. Чтобы устранить эту проблему, используйте только статические библиотеки или только динамические библиотеки для всего исполняемого файла и для всех библиотек, которые будут использоваться в исполняемом файле.

  • Эта ошибка может возникать, если символ является упакованой функцией (созданной компиляцией с помощью /Gy), и она была включена в несколько файлов, но была изменена между компиляциями. Чтобы устранить эту проблему, перекомпилируйте все файлы, включающие упаковаемую функцию.

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

  • Эта ошибка может возникать, если extern const переменная определена дважды и имеет другое значение в каждом определении. Чтобы устранить эту проблему, определите константу только один раз или используйте пространства имен или enum class определения для различения констант.

  • Эта ошибка может возникать, если вы используете uuid.lib в сочетании с другими файлами LIB, определяющими идентификаторы GUID (например, oledb.lib и adsiid.lib). Например:

    oledb.lib(oledb_i.obj) : error LNK2005: _IID_ITransactionObject
    already defined in uuid.lib(go7.obj)
    

    Чтобы устранить эту проблему, добавьте /FORCE:MULTIPLE в параметры командной строки компоновщика и убедитесь, что uuid.lib является первой ссылкой на библиотеку.