123
123

Reputation: 5824

#pragma once or include guards not working on extern funcs

I'm experiencing a very strange (and annoying) linker error on my project.

Say for example I have the file KernelExports.h:

#pragma once

extern "C"
{
    DWORD* KeTimeStampBundle;
    DWORD KeGetCurrentProcessType();
    //etc...
}

I then #include this in my stdafx.h and then add #include "stdafx.h" all all my *.cpp files. The problem is that now whenever I build I get a stream of linker errors: LNK2005: KeTimeStampBundle already defined in stdafx.obj. This should not be happening since the header file is only included in one file and is protected with include guards. The errors stop once I comment out the whole extern "C" block so I know that is what is causing the issue.

What's even stranger is when I add all these source files to a new project it builds without any problems. I don't see what the issue is here, can anyone enlighten me?

My IDE is Visual Studio 2008.

Upvotes: 1

Views: 1901

Answers (2)

James McNellis
James McNellis

Reputation: 355079

DWORD* KeTimeStampBundle;

This does not declare a function. It declares and defines an object of type DWORD* named KeTimeStampBundle. If you include this header file in multiple source files, you will have multiple definitions of this object (one from each source file in which the header is included).

Include guards and #pragma once ensure that something is only defined once in a given translation unit (source file). They have no effect on how things are defined across multiple translation units.

Upvotes: 5

Seth Carnegie
Seth Carnegie

Reputation: 75130

#pragma once doesn't keep your file from being included multiple times in the project, it keeps it from being included multiple times in the same file. So a.cpp and b.cpp can include the file once, and that defines KeTimeStampBundle twice.

To fix this, put the definition of KeTimeStampBundle and KeGetCurrentProcessType, etc. into a .cpp file and put extern DWORD* KeTimeStampBundle, etc in the header.

Note that this only applies to definitions, not declarations. extern ... and function prototypes are declarations, so they can be done multiple times, but definitions can only occur once in the entire project, accross all .cpp files.

Upvotes: 4

Related Questions