这是一个简单的测试代码来重现问题.
test.h:
#ifndef TEST_H_#define TEST_H_#ifdef __cplusplusextern "C" {#endifextern const char* strings[];#ifdef __cplusplus}#endif#endif /* TEST_H_ */
test.c的:
#include <test.h>const char* strings[] = {"string a","string b","string c" };
main.hpp
#ifndef MAIN_HPP_#define MAIN_HPP_#define STM32F4#include <test.h>#include <libopencm3/stm32/rcc.h>#include <libopencm3/stm32/gpio.h>#endif /* MAIN_HPP_ */
main.cpp中:
#include <main.hpp>int main(voID){ char s2[3][9]; rcc_periph_clock_enable(RCC_GPIOD); gpio_mode_setup(GPIOD,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,GPIO12); while (1) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 9; j++) { s2[i][j] = strings[i][j]; if (s2[i][j] == 'i') { gpio_toggle(GPIOD,GPIO12); } for (int k = 0; k < 1000000; k++) { __asm__("nop"); } } } }}
但是,当我在调试器中运行它时,我可以看到字符串[0](例如)指向的内存完全归零.
注意:while循环中的部分是不相关的,我刚刚添加它以获得一些反馈并避免编译器剥离未使用的字符串值.
那么我在这里做错了什么?
编辑
我在linux下使用Eclipse,gnu-arm-none-eabi.
编译器和链接器命令行和输出:
arm-none-eabi-g++ -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-move-loop-invariants -Wunused -Wuninitialized -Wall -Wextra -Wmissing-declarations -Wconversion -Wpointer-arith -Wpadded -Wshadow -Wlogical-op -Waggregate-return -Wfloat-equal -g3 -I"/home/andrea/ownCloud/src/arm/libopencm3/include" -I"/home/andrea/ownCloud/src/arm/testt/src" -std=gnu++11 -fabi-version=0 -fno-exceptions -fno-rtti -fno-use-cxa-atexit -fno-threadsafe-statics -Wabi -Wctor-dtor-privacy -Wnoexcept -Wnon-virtual-dtor -Wstrict-null-sentinel -Wsign-promo -MMD -MP -MF"src/main.d" -MT"src/main.o" -c -o "src/main.o" "../src/main.cpp"In file included from /home/andrea/ownCloud/src/arm/libopencm3/include/libopencm3/stm32/rcc.h:32:0,from /home/andrea/ownCloud/src/arm/testt/src/main.hpp:14,from ../src/main.cpp:20:/home/andrea/ownCloud/src/arm/libopencm3/include/libopencm3/stm32/f4/rcc.h:640:11: warning: padding struct to align 'rcc_clock_scale::plln' [-Wpadded] uint16_t plln; ^/home/andrea/ownCloud/src/arm/libopencm3/include/libopencm3/stm32/f4/rcc.h:644:11: warning: padding struct to align 'rcc_clock_scale::flash_config' [-Wpadded] uint32_t flash_config; ^Finished building: ../src/main.cppBuilding file: ../src/test.cInvoking: Cross ARM C Compilerarm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-move-loop-invariants -Wunused -Wuninitialized -Wall -Wextra -Wmissing-declarations -Wconversion -Wpointer-arith -Wpadded -Wshadow -Wlogical-op -Waggregate-return -Wfloat-equal -g3 -I"/home/andrea/ownCloud/src/arm/libopencm3/include" -I"/home/andrea/ownCloud/src/arm/testt/src" -std=gnu11 -Wmissing-prototypes -Wstrict-prototypes -Wbad-function-cast -MMD -MP -MF"src/test.d" -MT"src/test.o" -c -o "src/test.o" "../src/test.c"Finished building: ../src/test.cBuilding target: testt.elfInvoking: Cross ARM C++ linkerarm-none-eabi-g++ -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-move-loop-invariants -Wunused -Wuninitialized -Wall -Wextra -Wmissing-declarations -Wconversion -Wpointer-arith -Wpadded -Wshadow -Wlogical-op -Waggregate-return -Wfloat-equal -g3 -T "/home/andrea/ownCloud/src/arm/testt/src/stm32f407g-discovery.ld" -T "/home/andrea/ownCloud/src/arm/testt/src/libopencm3_stm32f4.ld" -nostartfiles -Xlinker --gc-sections -L"/home/andrea/ownCloud/src/arm/libopencm3/lib" -Wl,-Map,"testt.map" --specs=nano.specs -o "testt.elf" ./src/main.o ./src/test.o -lopencm3_stm32f4Finished building target: testt.elf
链接器脚本(不是最干净的脚本,我用它做了一些测试).
MEMORY{ rom (rx) : ORIGIN = 0x08000000,LENGTH = 1024K ram (rwx) : ORIGIN = 0x20000000,LENGTH = 128K}_stack_size = 0x400;/* Include the common ld script. */INCLUDE libopencm3_stm32f4.ld
libopencm3_stm32f4.ld:
/* Enforce emmition of the vector table. */EXTERN (vector_table)/* define the entry point of the output file. */ENTRY(reset_handler)/* define sections. */SECTIONS{ .text : { *(.vectors) /* Vector table */ *(.text*) /* Program code */ . = AliGN(4); *(.rodata*) /* Read-only data */ . = AliGN(4); } >rom /* C++ Static constructors/destructors,also used for __attribute__ * ((constructor)) and the likes */ .preinit_array : { . = AliGN(4); __preinit_array_start = .; KEEP (*(.preinit_array)) __preinit_array_end = .; } >rom .init_array : { . = AliGN(4); __init_array_start = .; KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) __init_array_end = .; } >rom .fini_array : { . = AliGN(4); __fini_array_start = .; KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) __fini_array_end = .; } >rom /* * Another section used by C++ stuff,appears when using newlib with * 64bit (long long) printf support */ .ARM.extab : { *(.ARM.extab*) } >rom .ARM.exIDx : { __exIDx_start = .; *(.ARM.exIDx*) __exIDx_end = .; } >rom . = AliGN(4); _etext = .; .data : { _data = .; *(.data*) /* Read-write initialized data */ . = AliGN(4); _edata = .; } >ram AT >rom _data_loadaddr = LOADADDR(.data); .bss : { *(.bss*) /* Read-write zero initialized data */ *(COMMON) . = AliGN(4); _ebss = .; } >ram . = AliGN(4); _end_bss = .; end = .; _end = .; _heap_bottom = .; _heap_top = ORIGIN(ram)+LENGTH(ram)-_stack_size; _stack_bottom =_heap_top; _stack_top = ORIGIN(ram) + LENGTH(ram); /* * The .eh_frame section appears to be used for C++ exception handling. * You may need to fix this if you're using C++. */ /disCARD/ : { *(.eh_frame) }}PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));
编辑
我正在调查这个问题,但我有点困惑.
启动代码包括以下内容:
for (src = &_data_loadaddr,dest = &_data; dest < &_edata; src++,dest++) { *dest = *src;}
所以对我来说似乎没问题.
.map文件提供以下信息:
.data 0x0000000020000000 0xc load address 0x000000000800038c 0x0000000020000000 _data = . *(.data*) .data.strings 0x0000000020000000 0xc ./src/test.o 0x0000000020000000 strings 0x000000002000000c . = AliGN (0x4) 0x000000002000000c _edata = . 0x000000002000000c _data = . *(.data*) 0x000000002000000c . = AliGN (0x4) 0x000000002000000c _edata = . 0x000000000800038c _data_loadaddr = LOADADDR (.data).igot.plt 0x000000002000000c 0x0 load address 0x0000000008000398
现在,当我运行调试器时,我从一开始就看到了& _data ==& _edata == 0x2000000c,我还注意到_data在.map文件中出现了两次.
那么,链接器脚本中是否有错误?
解决方法 正如奥拉夫在评论中所说,你并没有将你的字符串表声明为常量.因此,编译器/链接器将其视为初始化的读/写数据,而不是只读数据.也许你的初始化代码(在主入口点之前执行)没有正确地将初始化数据从闪存复制到RAM.
作为快速修复,尝试使您的字符串表保持不变:
char const * const strings[] = {"string a","string c" };
如果它工作,你可以调查内存初始化问题…看看给链接器的-nostartfiles参数,这可能会禁用启动代码(待确认)…
总结以上是内存溢出为你收集整理的C和C之间的全局变量全部内容,希望文章能够帮你解决C和C之间的全局变量所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)