Ошибка множественного включения для файла (ов) заголовка - C
У меня относительно небольшой проект с несколькими файлами (.c и.h). Я боролся с множественными ошибками включения (я думаю). Итак, я создал заголовочный файл master.h, в котором есть все остальные необходимые заголовочные файлы. ВСЕ заголовочные файлы имеют
#ifndef _MY_HEADER
#define _MY_HEADER
… Header body
#endif
охранники для предотвращения многократного включения. Каждый из моих файлов включает в себя файл master.h вверху. Вот как я мог бы ожидать, что это сработает.
- Первый скомпилированный файл будет видеть #include "master.h"
- Поскольку этот файл обрабатывается впервые, __MASTER еще не был бы определен, поэтому он будет обрабатывать файл.
- Компилятор пришел бы к включению следующего заголовочного файла, аналогично, он еще не был бы обработан, поэтому компилятор обработал бы его, затем он был бы определен и больше не обрабатывался.
- Это продолжается для всех заголовочных файлов в master.h до тех пор, пока все файлы не будут обработаны и определены, чтобы они больше не обрабатывались.
- То же самое относится и к файлу 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
,
Я не знаю о вашем скрипте компоновщика, но какой инструмент вы используете для компиляции?