繁体   English   中英

使用虚拟函数调用时节省堆栈空间

[英]conserve stack space when using virtual function calls

我目前正在用C ++开发STM32 µC。 基本上,我想向i²c添加一个抽象层,以使虚拟i²c总线实际上位于物理i²c总线上的多路复用器之后。

我们已经有一个将驱动程序和多路复用器逻辑结合在一起的驱动程序,那里的OOP部门显然缺乏...因此,我在I²C访问和虚拟总线实现中添加了一个间接级别,以使驱动程序与多路复用器逻辑脱钩并隐藏全局知识:

Device -> Virtual I²C -> I²C Multiplexer -> Abstracted I²C -> Low-Level I²C

现在我的问题基本上是,每个接口都必须定义一个传输函数

virtual
transmit(const uint8_t address,
         uint8_t *tx,
         size_t lentx,
         const uint8_t *rx,
         const size_t lenrx,
         const size_t timeout
         );

只是通过一些争论。 通常:

virtual
transmit(...) {

    this->driver->transmit(this->address, ...);

}

但是,事实证明,每个虚拟函数调用都会为我的堆栈要求增加多达40个字节,因为它们:

  1. 在堆栈上获取参数
  2. 为他们的函数调用分配堆栈
  3. 将输入复制到堆栈中新分配的部分的正确位置
  4. 执行函数调用
  5. 将输出复制回堆栈上正确的位置以容纳传入参数

现在,我们只是在最近才转而使用C ++,所以我对使用该语言进行嵌入式系统开发的微调仍然不了解。 但是,对我来说奇怪的是,已经存在三个级别的间接操作基本上会使我用尽堆栈空间...例如,这样我就无法通过遍历虚拟调用的方式丢失164个字节:设备到虚拟总线,虚拟总线到I²C多路复用器,即I²C到抽象I²C的多路复用器,在此处进行真正的调用。

理想的解决方案是显而易见的。 显然,虚函数调用仅应在需要时为需要传递和重新排序参数的其他变量分配尽可能多的空间:

Incoming: tx*, len, rx*, len, to
Allocate: tx*, len, rx*, len, to, ___
Reorder : ___, tx*, len, rx*, len, to
Add args: sla, tx*, len, rx*, len, to
     ---------- Call ----------
Reorder : tx*, len, rx*, len, to, ___
Dealloc : tx*, len, rx*, len, to
Output  : tx*, len, rx*, len, to

因此,真正的问题是:我可以强迫GCC注意到这种直通样式的行为,并强迫它保留尽可能多的堆栈空间吗? 我真的很茫然,因为我只使用POD开头...

尽管您不能说服gcc自动更改堆栈的布局,但是您肯定可以通过定义单个struct来手动设置堆栈,并在该struct上设置参数,并传递指向该struct的共享指针。

这是您可以执行的操作:

struct TxRxParams {
    uint8_t *tx;
    size_t lentx;
    const uint8_t *rx;
    const size_t lenrx;
};

现在,您可以分配一次TxRxParams ,并将指向它的指针传递给各种函数(无论是否虚拟),以节省堆栈空间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM