避免在内存中创建多个代码副本
Posted
技术标签:
【中文标题】避免在内存中创建多个代码副本【英文标题】:Avoid creating multiple copies of code in memory 【发布时间】:2013-06-13 22:32:37 【问题描述】:我是嵌入式系统开发的新手,不习惯使用很少的程序内存(在本例中为 16kB)。我希望能够创建全局变量、数组和函数,我可以从程序中的任何位置访问它们,而 只存在于内存中的一个地方。我目前的方法是使用静态类成员和方法,只需包含头文件即可使用(例如#include "spi.h"
)。
对于我正在尝试做的事情,最好的方法是什么?
这是一个示例类。据我了解,.cpp中_callback
之类的变量和call()
之类的函数定义只会出现在spi.o中,所以它们只会在内存中出现一次,但我可能会混淆。
spi.h:
#ifndef SPI_H_
#define SPI_H_
#include "msp430g2553.h"
class SPI
public:
typedef void (*voidCallback)(void);
static voidCallback _callback;
static char largeArray[1000];
static __interrupt void USCIA0TX_ISR();
static void call();
static void configure();
static void transmitByte(unsigned char byte, voidCallback callback);
;
#endif /* SPI_H_ */
spi.cpp:
#include "spi.h"
SPI::voidCallback SPI::_callback = 0;
char SPI::largeArray[] = /* data */ ;
void SPI::configure()
UCA0MCTL = 0;
UCA0CTL1 &= ~UCSWRST;
IE2 |= UCA0TXIE;
void SPI::transmitByte(unsigned char byte, voidCallback callback)
_callback = callback;
UCA0TXBUF = byte;
void SPI::call()
SPI::_callback();
#pragma vector=USCIAB0TX_VECTOR
__interrupt void SPI::USCIA0TX_ISR()
volatile unsigned int i;
while (UCA0STAT & UCBUSY);
SPI::call();
【问题讨论】:
要简单地包含标头并开始使用“SPI”,只需使用Singleton pattern,在嵌入式系统中很常见的是你有一个外围设备,只有一个对象来处理硬件,不允许更多对象。 ,您也可以使用factory pattern 来允许例如一定数量的对象(SPI 通道) 【参考方案1】:你写的类的数据成员和成员函数只会在内存中定义一次。如果它们没有标记为静态,则成员函数仍然只会在内存中定义一次。将为您创建的每个对象在内存中创建一次非静态数据成员,因此如果您只创建一个 SPI
对象,您只会获得其非静态数据成员的一份副本。简短版:您正在解决一个非问题。
【讨论】:
【参考方案2】:根据 Pete 的说法,静态不会影响代码加倍,只会影响成员变量。在您的示例中,除了 _callback var(您将其称为错误)之外,静态非静态内存使用量之间的差异为 0。并且如果该类被多次创建,那么一个变量只会加倍。
如果您希望代码在不使用时不存在于内存中,请查看覆盖或某种动态链接过程。 DLL 类型代码对于 16K 来说可能是主要的过度杀伤,但使用压缩代码覆盖可能会对您有所帮助。
另外,请注意库中代码中的额外链接。仔细检查您的 .map 文件是否因无害的函数调用而导致代码膨胀。例如,单个 printf() 调用将链接到各种 vargs 的东西,如果它是唯一使用它的东西。软件浮点也一样(如果你默认没有 FP 单元。)
【讨论】:
抱歉,“作为错误调用”是我问的另一个问题的遗留问题。我用一个示例大数组更新了这个问题,以说明我在说什么。 在您的新情况下,除了为了(可疑)安全起见将其设为单例类型对象外,仍然没有理由将其声明为静态。同样,你最好研究一下你的地图文件,看看你的臃肿是从哪里来的,然后从那里解决问题。以上是关于避免在内存中创建多个代码副本的主要内容,如果未能解决你的问题,请参考以下文章