Подтвердить что ты не робот

Как удалить предупреждения LNK4217 и LNK4049

У меня есть предупреждения о шаге ссылки. Эти предупреждения появляются только в режиме деблокирования.

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

Когда я создаю библиотеку, у меня нет предупреждений. Но когда я создаю свой исполняемый файл, по ссылке у меня есть предупреждения LNK4217 и LNK4049. Например:

3>DaemonCommon.lib(Exception.obj) : warning LNK4217: locally defined symbol [email protected]@@[email protected]@Z (public: __thiscall std::exception::exception(char const * const &)) imported in function "public: __thiscall std::bad_alloc::bad_alloc(char const *)" ([email protected]@@[email protected]@Z)
3>DaemonCommon.lib(CommAnetoException.obj) : warning LNK4217: locally defined symbol [email protected]@@[email protected]@Z (public: __thiscall std::exception::exception(char const * const &)) imported in function "public: __thiscall std::bad_alloc::bad_alloc(char const *)" ([email protected]@@[email protected]@Z)

Я прочитал в MSDN, эти предупреждения могут быть вызваны объявлением __declspec (dllimport). Но, в моих классах моей библиотеки, я не так провозгласил это. Например, вот мой класс Exception:

#ifndef _EXCEPTION_HPP__
#define _EXCEPTION_HPP__

#include <string>

namespace Exception
{
    class Exception  
    {
    public:
        // Constructor by default
        Exception();

        // Constructor parametrized
        Exception(std::string& strMessage);

        // Get the message of the exception
        virtual std::string getMessage() const;

        // Destructor
        virtual ~Exception();

    protected:

        // String containing the message of the exception
        std::string mStrMessage;
    };
}

#endif

Может кто-нибудь сказать мне, почему появляются эти предупреждения и как их удалить?

4b9b3361

Ответ 1

Это вызвано __declspec(import) символами, указанными как "импортированные", т.е. на public: __thiscall std::exception::exception(char const * const &). Это может быть вызвано несоответствием между параметром компилятора для выбора времени выполнения (/MT (статическая многопотоковая среда выполнения) v.s. /MD (динамическое время выполнения)) и опциями препроцессора (_DLL define). В частности, эти предупреждения появятся, если вы скомпилируете /MT (или /MTd в конфигурации отладки), но _DLL каким-то образом определился.

Итак, убедитесь, что вы не определяете _DLL, когда не компилируете с помощью /MD.

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

Ответ 2

Несоответствие __declspec (dllexport)/__ declspec (dllimport) также может происходить из-за функций/классов, определенных заголовком; например: Вы создаете общую библиотеку (.dll), которая использует смесь функций/классов Header-Defined/ "Only" и связанных функций/классов (без определенного файла интерфейса они должны использовать __declspec (dllexport) при компиляции разделяемой библиотеки и __declspec (dllimport) при использовании). Общей ошибкой является определение __declspec (dllexport)/__ declspec (dllimport) для частей, которые фактически являются только заголовками и, следовательно, не являются частью самой скомпилированной библиотеки.

Ответ 3

Это не относится к проблеме OP, но я также видел LNK4217 при связывании в локальной библиотеке с исполняемым файлом, где нет несоответствия библиотеки времени выполнения.

Некоторые библиотеки требуют определения препроцессора при создании их как статических (независимо от того, используется ли статическая или динамическая среда исполнения). Например, libzmq (0MQ) требует, чтобы символ ZMQ_STATIC определялся при построении статической библиотеки. В противном случае вы получите LN2417 при связывании библиотеки с исполняемым файлом.

Ответ 4

Немного info от Russ Keldorph о том, что на самом деле делает declspec (dllimport). (Предлагает использовать переключатель /QSimplicit-import-.)