Множественное определение глобальной переменной

Возможный дубликат:
постоянные переменные, не работающие в заголовке

В моем файле заголовка, который я использую для создания общего объекта, у меня есть следующее:

#ifndef LIB_HECA_DEF_H_
#define LIB_HECA_DEF_H_

struct dsm_config {
    int auto_unmap;
    int enable_copy_on_access;
};

enum { NO_AUTO_UNMAP, AUTO_UNMAP } unmap_flag;
enum { NO_ENABLE_COA, ENABLE_COA } coa_flag;

const struct dsm_config DEFAULT_DSM_CONFIG = { AUTO_UNMAP, NO_ENABLE_COA };

<more code ...>

#endif

При компиляции я получаю следующую ошибку:

cc -g -Wall -pthread libheca.c dsm_init.c -DDEBUG    master.c   -o master
/tmp/cciBnGer.o:(.rodata+0x0): multiple definition of `DEFAULT_DSM_CONFIG'
/tmp/cckveWVO.o:(.rodata+0x0): first defined here
collect2: ld returned 1 exit status
make: *** [master] Error 1

Любые идеи, почему?

Ответ 1

Поскольку при каждом включении в файл файла реализации создается новый экземпляр вашей структуры (и сохраняется в объектном файле).

Чтобы этого избежать, просто объявите структуру как "extern" в файле заголовка и инициализируйте ее в файле реализации:

// In your header file: 
extern const struct dsm_config DEFAULT_DSM_CONFIG;

// In your *.c file:
const struct dsm_config DEFAULT_DSM_CONFIG = { AUTO_UNMAP, NO_ENABLE_COA };

Это решит вашу проблему.

Ответ 2

В языке C const объекты имеют внешнюю связь по умолчанию (в отличие от С++, где по умолчанию они имеют внутреннюю привязку). Таким образом, в вашем коде вы создали несколько определений объекта DEFAULT_DSM_CONFIG с внешней связью - явное нарушение правил определения языка C.

Объявите свой объект как static const (если вы не возражаете против наличия нескольких объектов с внутренней связью) или удалите определение из файла заголовка (оставьте там только не определяющее объявление extern const).

В любом случае, вопрос задавался много раз. См. постоянные переменные, не работающие в заголовке, или выполните поиск.

Ответ 3

Каждый c файл, содержащий ваш файл заголовка, имеет строку

const struct dsm_config DEFAULT_DSM_CONFIG = {AUTO_UNMAP, NO_ENABLE_COA};

Итак, каждый из этих файлов c определяет переменную dsm_config. Если вам нужна только одна переменная dsm_config, вам нужно изменить объявление в файле заголовка на

extern const struct dsm_config DEFAULT_DSM_CONFIG;

и добавьте определение

const struct dsm_config DEFAULT_DSM_CONFIG = {AUTO_UNMAP, NO_ENABLE_COA};

только в одном файле c.

Другим, не очень хорошим решением является изменение файла заголовка на

static const struct dsm_config DEFAULT_DSM_CONFIG = {AUTO_UNMAP, NO_ENABLE_COA};

Затем каждый c файл определяет его собственный dsm_config, который не отображается для других единиц перевода во время ссылки.

Ответ 4

Каждый исходный файл (.c, not.h) скомпилирован отдельно. В каждой из этих компиляций объявление dsm_config с инициализатором (часть = { values… }) создает определение dsm_config. Таким образом, вся программа имеет несколько определений.

Как правило, файлы заголовков должны только объявлять объекты и не определять их. Для этого удалите инициализатор в файле заголовка, оставив только объявление без инициализатора. В одном исходном файле определите dsm_config, повторив объявление с помощью инициализатора.