#pragma один раз или включить охранников, не работающих над внешними функциями - PullRequest
1 голос
/ 10 августа 2011

Я испытываю очень странную (и раздражающую) ошибку компоновщика в моем проекте.

Скажем, например, у меня есть файл KernelExports.h:

#pragma once

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

Затем я #include это в моем stdafx.h, а затем добавить #include "stdafx.h" все мои * .cpp файлы. Проблема в том, что теперь всякий раз, когда я строю, я получаю поток ошибок компоновщика: LNK2005: KeTimeStampBundle already defined in stdafx.obj. Этого не должно быть, поскольку заголовочный файл включен только в один файл и защищен включенными защитными устройствами. Ошибки прекращаются, когда я закомментирую весь блок extern "C", поэтому я знаю, что именно это является причиной проблемы.

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

Моя среда разработки - Visual Studio 2008.

Ответы [ 2 ]

5 голосов
/ 10 августа 2011
DWORD* KeTimeStampBundle;

Это не объявляет функцию.Он объявляет и определяет объект типа DWORD* с именем KeTimeStampBundle.Если вы включите этот заголовочный файл в несколько исходных файлов, у вас будет несколько определений этого объекта (по одному из каждого исходного файла, в который включен заголовок).

Включите охранники и #pragma once гарантируют, что что-то толькоопределяется один раз в заданной единице перевода (исходный файл).Они не влияют на то, как вещи определяются в нескольких единицах перевода.

4 голосов
/ 10 августа 2011

#pragma once не удерживает ваш файл от многократного включения в проект, он удерживает его от многократного включения в один и тот же файл . Таким образом, a.cpp и b.cpp могут включать файл один раз, и это определяет KeTimeStampBundle дважды.

Чтобы исправить это, поместите определение KeTimeStampBundle и KeGetCurrentProcessType и т. Д. В файл .cpp и поместите extern DWORD* KeTimeStampBundle и т. Д. В заголовок.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...