如何删除警告LNK4217和LNK4049

22

在链接步骤中,我收到了警告。这些警告仅在发布模式下出现。

我的程序由两部分组成:生成 .lib 的库和使用该库的可执行文件。

当我构建库时,没有警告。但是当我构建可执行文件时,在链接时我会收到警告 LNK4217 和 LNK4049。例如:

3>DaemonCommon.lib(Exception.obj) : warning LNK4217: locally defined symbol ??0exception@std@@QAE@ABQBD@Z (public: __thiscall std::exception::exception(char const * const &)) imported in function "public: __thiscall std::bad_alloc::bad_alloc(char const *)" (??0bad_alloc@std@@QAE@PBD@Z)
3>DaemonCommon.lib(CommAnetoException.obj) : warning LNK4217: locally defined symbol ??0exception@std@@QAE@ABQBD@Z (public: __thiscall std::exception::exception(char const * const &)) imported in function "public: __thiscall std::bad_alloc::bad_alloc(char const *)" (??0bad_alloc@std@@QAE@PBD@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

有人能告诉我这些警告为什么会出现以及如何删除它们吗?

6个回答

27
这是由于在被称为“导入”的符号上使用了__declspec(import),例如public: __thiscall std::exception::exception(char const * const &)。这可能是由于编译器运行时选择选项(/MT(静态多线程运行时)与/MD(动态运行时))和预处理器选项(_DLL定义)之间不匹配导致的。特别是如果你使用/MT(或/MTd调试配置),但一些程序中却定义了_DLL,则会出现这些警告。

因此,请确保在不使用/MD编译时不要定义_DLL

另外,将所有库编译为与可执行文件相同的运行时很重要,因此请检查所有项目的运行时选择是否匹配,并链接任何第三方库的适当版本。


3
实际上,这是因为我的可执行项目是定义在“多线程 DLL \MD”而不是“多线程\MT”上...我不知道为什么...所以谢谢;-) - Cedekasme

2

这段内容与OP的问题无关,但我也曾在将本地库链接到可执行文件时看到过LNK4217错误,而且没有运行库不匹配的情况。

有些库在构建静态库时需要预处理器定义(无论是使用静态还是动态运行时)。例如,libzmq(0MQ)要求在构建静态库时定义符号ZMQ_STATIC。否则,当将库链接到可执行文件时会出现LN2417错误。


1
这对于AsmJit也是正确的。在这种情况下,定义ASMJIT_STATIC。 - Dess

2
__declspec(dllexport)/__declspec(dllimport)不匹配也可能是由于头文件定义的函数/类引起的。
例如:
您正在构建一个使用Header-Defined /“Only”函数/类和链接函数/类(没有特定接口文件需要在编译共享库时使用__declspec(dllexport),在使用它时使用__declspec(dllimport))混合的共享库(.dll)。
常见错误是为实际上是头文件的部分定义__declspec(dllexport)/__declspec(dllimport),因此它们不是编译后的库的一部分。

2
来自Russ Keldorph的一些信息,关于declspec(dllimport)实际上是什么。(建议使用/QSimplicit-import-开关。)

1

检查是否在一个配置了Visual Studio的动态库(.dll)中错误地使用了__declspec(dllimport)而不是__declspec(dllexport)


0

当使用 $<TARGET_OBJECTS:mylib> 链接 cmake OBJECT 库mylib 到其他代码时,我收到了同样的警告。

我通过使用 /Zl(省略默认库名称)编译选项构建 OBJECT 库以解决这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接