Ошибка множественного включения для файла (ов) заголовка - C

У меня относительно небольшой проект с несколькими файлами (.c и.h). Я боролся с множественными ошибками включения (я думаю). Итак, я создал заголовочный файл master.h, в котором есть все остальные необходимые заголовочные файлы. ВСЕ заголовочные файлы имеют

#ifndef _MY_HEADER
#define _MY_HEADER
… Header body
#endif

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

  1. Первый скомпилированный файл будет видеть #include "master.h"
  2. Поскольку этот файл обрабатывается впервые, __MASTER еще не был бы определен, поэтому он будет обрабатывать файл.
  3. Компилятор пришел бы к включению следующего заголовочного файла, аналогично, он еще не был бы обработан, поэтому компилятор обработал бы его, затем он был бы определен и больше не обрабатывался.
  4. Это продолжается для всех заголовочных файлов в master.h до тех пор, пока все файлы не будут обработаны и определены, чтобы они больше не обрабатывались.
  5. То же самое относится и к файлу master.h. Как только он обработан и завершен, он не будет обработан снова из-за охраны.

Разве это не должно предотвратить множественное включение?

Итак, вот ошибки.

Building target: My_Project_Bootloader.axf
Invoking: GNU ARM C Linker
arm-none-eabi-gcc -g3 -gdwarf-2 -mcpu=cortex-m3 -mthumb -T "C:/Users/Greg/SimplicityStudio/v4_workspace/My_Project_Bootloader/GNU ARM v4.9.3 - Debug/My_Project_Bootloader_custom.ld" -nostdlib -L"C:\GCC_STUFF" --specs=nosys.specs -Xlinker --gc-sections -Xlinker -Map="My_Project_Bootloader.map" -lm -lgcc -lc -o My_Project_Bootloader.axf "./Source/aeabi_memset-thumb.o" "./Source/crt0.o" "./Source/em_emu.o" "./Source/functions.o" "./Source/main.o" "./Source/startup_efm32jg1b.o" "./Source/interrupts.o" 
./Source/main.o:(.rodata.const_ModBusIDReg+0x0): multiple definition of `const_ModBusIDReg'
./Source/functions.o:(.rodata.const_ModBusIDReg+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
make: *** [My_Project_Bootloader.axf] Error 1

Я отредактировал / удалил некоторую информацию в этом посте, потому что оказалось, что она не связана. Похоже, что проблемы с "множественными определениями" у линкера не были связаны с фактическими "множественными определениями" или включениями для какой-либо переменной. Вместо этого это выглядит так, как если бы это было связано с одновременным объявлением и определением переменной (в данном случае const in flash). Как только я разделил объявление (я) в файл заголовка, а фактическое определение или присвоение в файл.c, проблемы исчезли. Вот пример исправления для одной из проблемных "переменных". Сейчас я уделю гораздо больше внимания аспектам объявления и определения переменных. Используемые инструменты были GCC. Спасибо за все комментарии.

// boot.h
// declare const array
const unsigned char const_ModBusIDReg[7][48];


// boot.c
#include boot.h

// define const array
const unsigned char const_ModBusIDReg[7][48] =
{
"String1",          // reg00
"String2",          // reg01
"String3",          // reg02
"String4",          // reg03
"String5",          // reg04
"String6",          // reg05
"String7"           // reg06
 };

2 ответа

Проблема связана с проблемой компоновщика, а не с исходным файлом. Это не будет решено путем предотвращения многократного включения заголовков в одну единицу перевода (TU - исходный файл плюс включенные файлы).

Похоже, у вас есть четыре символа (const_ModBusIDReg, const_ModBusRegAttr,const_ModBusRegDefaults,const_ModBusRegLimits), которые определены в нескольких исходных файлах, возможно, потому что вы определяете, а не объявляете их в заголовке.

Переменные, указанные в заголовке, должны иметь префикс extern - иначе это определения, а не декларации.

Обычно #ifndef HEADER_NAME как вы избежали любых в том числе конфликтов. Но вы сказали "Каждый из моих файлов включает в себя master.h", поэтому я предлагаю, чтобы ваш .c не должно включать ничего, кроме того, что они сами связаны .h, (Это может быть уже так).

Также остерегайтесь .c,

Я не знаю о вашем скрипте компоновщика, но какой инструмент вы используете для компиляции?

Другие вопросы по тегам