c++ - 静态变量未初始化

标签 c++ compilation arm

作为学校项目,我正在为 Raspberry Pi 开发一个小内核。我们遇到了静态变量初始化的问题:似乎那些根本没有初始化。我找到了一些相关主题,但到目前为止还没有人提出解决方案,尽管 this帮助我理解了这个问题(至少,我认为)。

所有代码都可以找到on this repository ,但我会尝试在这里总结相关代码。

从显示问题的项目中提取的代码:(kernel/src/kernel.cpp)

static int staticVal = 42;

void doStuff() { // Prevent the compiler from optimizing the value of staticVal
    staticVal++;
}

__attribute__((section(".init")))
int main(void) {
    //...
    gpio::blinkValue(staticVal); // Displays the value through LEDs
    //...
}

然后使用(eg)编译代码

arm-none-eabi-g++ -O2 -std=c++11 -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s -nostartfiles -Wall -Wextra -pedantic -I src/ -I uspi/include -DHW_PI_1B -c src/[file].cpp -o _build/[file].o

并使用相同的选项构建成二进制文件,最后使用

组装成kernel.img
arm-none-eabi-ld --no-undefined _build/master.bin -Map _build/kernel.map -o _build/output.elf -T kernel.ld
arm-none-eabi-objcopy _build/output.elf -O binary kernel.img

(您可以直接阅读 Makefile 以获取更多详细信息:github.com/tobast/sysres-pikern/blob/staticNotWorking/kernel/Makefile)。

使用的链接器脚本也可能是问题所在,因为我们试图在不知道自己在做什么的情况下弄清楚如何编写一个可以工作的链接器脚本(我们使用来自另一个项目的修改后的链接器脚本): github.com/tobast/sysres-pikern/blob/staticNotWorking/kernel/kernel.ld

_start = 0x8000;
ENTRY(_start)

SECTIONS {
    .init 0x8000 : {
        *(.init)
    }

    .text : {
        *(.text)
    }

    .data : {
        *(.data)
    }

    .bss : {
        *(.bss)
    }
}

以这种方式生成的程序显示了一个明显的随机值(无论如何,它与期望值 42 无关)。

到目前为止,我所了解的是操作系统应该负责在实际启动程序之前初始化静态变量,但是由于我们正在编写操作系统,所以没有人为我们做这件事。当然,我们可以手动初始化这些变量(通过为此目的调用启动函数),但这将是一个丑陋而痛苦的解决方案......

我们是否缺少任何 g++/链接器选项,或者我们的链接器脚本有问题?

谢谢!

最佳答案

我看到了几个问题:

  • 您的部分未与页面对齐,即链接器脚本中的 ALIGN(0x1000)

  • 您没有设置堆栈和清零 bss 部分的“启动”ASM 脚本。

我不知道这样的脚本在 ARM 上会是什么样子(我习惯了 x86),但这里有一个例子:

        .section "vectors"
reset:  b     start
undef:  b     undef
swi:    b     swi
pabt:   b     pabt
dabt:   b     dabt
        nop
irq:    b     irq
fiq:    b     fiq

        .text
start:
        @@ Copy data to RAM.
        ldr   r0, =flash_sdata
        ldr   r1, =ram_sdata
        ldr   r2, =data_size

        @@ Handle data_size == 0
        cmp   r2, #0
        beq   init_bss
copy:
        ldrb   r4, [r0], #1
        strb   r4, [r1], #1
        subs   r2, r2, #1
        bne    copy

init_bss:
        @@ Initialize .bss
        ldr   r0, =sbss
        ldr   r1, =ebss
        ldr   r2, =bss_size

        @@ Handle bss_size == 0
        cmp   r2, #0
        beq   init_stack

        mov   r4, #0
zero:
        strb  r4, [r0], #1
        subs  r2, r2, #1
        bne   zero

init_stack:
        @@ Initialize the stack pointer
        ldr   sp, =0xA4000000

        bl    main

stop:   b     stop

当然,您需要修改它以匹配内核的语义。

关于c++ - 静态变量未初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37137064/

相关文章:

c++ - 异或、非或(使用 Eigen 矩阵库)的 bool 乘法

java - 我可以使用带有较新 JDK 的 ant 为较旧的 Java 版本编译 java,以便它在编译使用较新 API 的代码时生成输出吗?

编译输出代码

linux - ARM 不会产生未对齐的异常

c - Atmel SAMD21 DMA 中止问题

optimization - 范围编码器 : How to get rid of divisions?

c++ - 尝试读取或写入 protected 内存。这通常表明其他内存已损坏

c++ - vector::clear() 导致段错误

c++ - 如何使用 OpenSSL 编译一个简单的程序?

compilation - 为什么 Rust hello world 会尝试读取/proc 和/sys