1

我有一个相对较小的项目,只有几个文件(.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)所致。一旦我将声明拆分为头文件,并将实际定义或分配拆分为 .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
 };
4

2 回答 2

0

通常#ifndef HEADER_NAME像你一样避免任何包括冲突。但是您说“我的每个文件都包含 master.h”,所以我建议您.c不应该包含除它们自己关联的任何其他内容.h。(可能已经是这种情况了)。

另外,请注意包含.c.

我不知道你的链接器脚本,但你用什么工具来编译?

于 2018-05-17T15:50:11.410 回答
0

问题是链接器问题,而不是每个源文件问题。它不会通过阻止标题多次包含在单个翻译单元(TU - 源文件加上包含的文件)中来解决。

您似乎有四个符号(const_ModBusIDReg, const_ModBusRegAttr, const_ModBusRegDefaults, const_ModBusRegLimits),它们在多个源文件中定义,可能是因为您在标头中定义而不是声明它们。

头文件中引用的变量必须以extern— 为前缀,否则,它们是定义,而不是声明。

于 2018-05-17T15:53:21.313 回答