概括
我有几个 C 源文件,它们都声明了单独的同名静态全局变量。我的理解是每个文件中的静态全局变量应该只在该文件中可见,并且不应该应用外部链接,但实际上我在调试时可以看到同名变量共享相同的内存地址。
就像static
关键字被忽略,而全局变量被视为extern
代替。为什么是这样?
示例代码
富.c:
/* Private variables -----------------------------------*/
static myEnumType myVar = VALUE_A;
/* Exported functions ----------------------------------*/
void someFooFunc(void) {
myVar = VALUE_B;
}
酒吧.c:
/* Private variables -----------------------------------*/
static myEnumType myVar = VALUE_A;
/* Exported functions ----------------------------------*/
void someBarFunc(void) {
myVar = VALUE_C;
}
baz.c:
/* Private variables -----------------------------------*/
static myEnumType myVar = VALUE_A;
/* Exported functions ----------------------------------*/
void someBazFunc(void) {
myVar = VALUE_D;
}
调试观察
myVar = ...
在每个函数内的行上设置断点。- 从 main 中按顺序调用
someFooFunc
、someBarFunc
和someBazFunc
。 - Inside
someFooFunc
myVar
最初设置为VALUE_A
,在跨过它设置为 的线后VALUE_B
。 - 由于某种原因,内部
someBarFunc
myVar
最初设置为VALUE_B
在跨行之前,而不是VALUE_A
我所期望的,这表明链接器可能已经合并了基于它们具有相同名称的单独的全局变量。 someBazFunc
调用时也是如此。- 如果我使用调试器来评估
&myVar
每个断点处何时给出相同地址的值。
工具和标志
工具链:GNU ARM GCC (6.2 2016q4)
编译器选项:
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mlong-calls -O1 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -fno-move-loop-invariants -Wall -Wextra -g3 -DDEBUG -DTRACE -DOS_USE_TRACE_ITM -DSTM32L476xx -I"../include" -I"../system/include" -I"../system/include/cmsis" -I"../system/include/stm32l4xx" -I"../system/include/cmsis/device" -I"../foo/inc" -std=gnu11 -MMD -MP -MF"foo/src/foo.d" -MT"foo/src/foo.o" -c -o "foo/src/foo.o" "../foo/src/foo.c"
链接器选项:
arm-none-eabi-g++ -mcpu=cortex-m4 -mthumb -mlong-calls -O1 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -fno-move-loop-invariants -Wall -Wextra -g3 -T mem.ld -T libs.ld -T sections.ld -nostartfiles -Xlinker --gc-sections -L"../ldscripts" -Wl,-Map,"myProj.map" --specs=nano.specs -o ...