在编译stm32 arm gcc工程中遇到的一些关于C++的问题

在编译stm32 arm gcc工程中遇到的一些关于C++的问题

环境 : vscode Embeded IDE插件。

工程 : 使用cubemx生成的stm32 gcc工程。

​ 我在尝试移植以前在esp-idf写的一个用c++实现的ssd1306组件,遇到了几个问题。首先是virtual析构器无法通过编译,这个是小问题,查询万能的互联网发现是没有链接stdc++库,在链接器后面加入-lstdc++就能解决。(但是我还有其他类,没有使用virtual修饰析构器,却能正常编译通过)。

编译器报错: undefined reference to `operator delete(void)'*
报错位置: Ssd1306::~Ssd1306()

c:/arm gnu toolchain arm-none-eabi/12.2 mpacbti-rel1/bin/../lib/gcc/arm-none-eabi/12.2.1/../../../../arm-none-eabi/bin/ld.exe: warning: ./build/Debug/MiniWitch.elf has a LOAD segment with RWX permissions
c:/arm gnu toolchain arm-none-eabi/12.2 mpacbti-rel1/bin/../lib/gcc/arm-none-eabi/12.2.1/../../../../arm-none-eabi/bin/ld.exe: ./build/Debug/USER/device/ssd1306/src/ssd1306.o: in function `Ssd1306::~Ssd1306()':
d:\UnderwayProject\MiniWitch\firmware/./USER/device/ssd1306/src/ssd1306.cpp:18: undefined reference to `operator delete(void*)'
c:/arm gnu toolchain arm-none-eabi/12.2 mpacbti-rel1/bin/../lib/gcc/arm-none-eabi/12.2.1/../../../../arm-none-eabi/bin/ld.exe: ./build/Debug/USER/device/ssd1306/src/ssd1306.o:(.rodata._ZTI7Ssd1306+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info'

在链接器中加入stdc++就可以处理以上报错。

​ 第二个遇到的问题比较麻烦,以前用C语言写单片机用的比较多,虽然有面向对象的思想,但是实例一般都是直接做为静态变量。这次因为图简单,直接用了个静态实例实现单例模式,结果在构造的时候出了大问题。

构造器

static Ssd1306  ssd1306( &oled_spi4_handle );

Ssd1306::Ssd1306(Ssd1306_hal_handle_t *hal_t){
    _hal_t = *hal_t;
    // _isSelfBuf = false;
    _hal_t.init(_hal_t.ctx);
    softInit();
}

构造器的底层调用

static void ssd1306_delay(uint16_t ms){
    if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING )
    {
        vTaskDelay( ms / portTICK_PERIOD_MS );
    }else{
        HAL_Delay(ms);
    }
}

​ 这个用于初始化ssd1306的delay函数看上去没什么大问题,结果运行的时候直接阻塞…。定位了一下原因,hal_timer压根没起来,用openOCD debug了一下,发现了问题。

LoopFillZerobss:
  cmp r2, r4
  bcc FillZerobss

/* Call static constructors */
    bl __libc_init_array
/* Call the application's entry point.*/
  bl sdk_main
  bx lr
.size Reset_Handler, .-Reset_Handler

​ 重点就是__libc_init_array函数,这个应该是c++标准库中的函数,用于构造(初始化)一些静态或者全局实例的,在进入sdk_main之前,程序就跑到了Ssd1306的实例的构造器中去了,而构造器依赖了hal库,hal库在sdk_main中才进行了初始化,导致在delay直接阻塞…,当然softInit里面也调用了hal的一些spi相关的接口,没有在delay阻塞后面也会导致指针踩空然后挂掉。
​ 我当前想到的办法就是不使用静态或者全局的实例,在sdk_main运行完后直接new到全局去,但是单片机这点小heap确实有点难顶。所以后期打算直接改启动文件,将hal库的初始化单独封装起来,在 libc_init_array 之前调用,hal库全部由c语言实现,应该问题不大,libc_init_array调用完之后,在进入用户的main函数。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值