C和C之间的全局变量

C和C之间的全局变量,第1张

概述我正在为ARM STM32F4开发一个混合C/C++程序,但是我在访问C部分中定义的全局变量时遇到了问题. 这是一个简单的测试代码来重现问题. test.h: #ifndef TEST_H_#define TEST_H_#ifdef __cplusplusextern "C" {#endifextern const char* strings[];#ifdef __cpluspl 我正在为ARM STM32F4开发一个混合C/C++程序,但是我在访问C部分中定义的全局变量时遇到了问题.
这是一个简单的测试代码来重现问题.

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之间的全局变量所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1239480.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存