我的项目遇到了一个非常奇怪(又烦人)的链接器错误。
比方说,我有文件KernelExports.h:
#pragma once
extern "C"
{
DWORD* KeTimeStampBundle;
DWORD KeGetCurrentProcessType();
//etc...
}
然后我在我的stdafx.h中#include
然后添加#include "stdafx.h"
我所有的* .cpp文件。问题是,现在每当我构建时,我都会遇到链接器错误:LNK2005: KeTimeStampBundle already defined in stdafx.obj
。这不应该发生,因为头文件只包含在一个文件中并受到包含保护的保护。一旦我注释掉整个extern "C"
块,错误就会停止,所以我知道这就是导致问题的原因。
更奇怪的是,当我将所有这些源文件添加到它构建的新项目时没有任何问题。我不知道这里有什么问题,任何人都可以启发我吗?
我的IDE是Visual Studio 2008。
答案 0 :(得分:5)
DWORD* KeTimeStampBundle;
这不会声明一个函数。它声明了并定义了一个名为DWORD*
的{{1}}类型的对象。如果将此头文件包含在多个源文件中,则您将拥有此对象的多个定义(每个源文件中包含一个头文件)。
包括警卫和KeTimeStampBundle
确保某些内容仅在给定翻译单元中定义(源文件)。它们对多个翻译单元的定义方式没有影响。
答案 1 :(得分:4)
#pragma once
不会阻止您的文件多次出现在项目中,因此不会在同一文件中多次包含该文件。因此,a.cpp
和b.cpp
可以包含一次文件,并定义KeTimeStampBundle
两次。
要解决此问题,请将KeTimeStampBundle
和KeGetCurrentProcessType
等的定义放入.cpp
文件中,并将extern DWORD* KeTimeStampBundle
等放入标题中。
请注意,这仅适用于 definitions ,而不适用于声明。 extern ...
和函数原型是声明,所以它们可以多次完成,但定义只能在整个项目中出现一次,覆盖所有.cpp
个文件。