PFTL101B 20KN 3BSE004203R1
PFTL101B 20KN 3BSE004203R1
虽然当今的嵌入式系统的内存比之以K计数的时代已经有了很大的提高,但是随着软件规模的增长,内存不足的问题依然时时困扰着系统架构师。有一些原则,架构师在进行设计决策的时候可以参考:
2.3.1. 虚拟内存技术
有一些嵌入式设备需要处理巨大的数据量,而这些数据不可能全部装入内存中。一些嵌入式操作系统不提供虚拟内存技术,比如WinCE4.2每个程序最多只能使用32M内存。对这样的应用,架构师应该特别设计自己的虚拟内存技术。所谓的虚拟内存技术的核心是,将暂时不太可能使用的数据移出内存。这涉及到一些技术点:
引用计数,正在使用的数据不能移出。
使用预测,预测下一个阶段某个数据的使用可能性。基于预测移出数据或者提前装入数据。
占位数据/对象。
高速缓存。在复杂数据结果下缓存高频率使用的数据,直接访问。
快速的持久化和装载。
下图是一个全国电信机房管理系统的界面示意图:
每个节点下都有大量的数据需要装载,可以使用上述技术将内存占用降到最低。
2.3.2. 两段式构造
在内存有限的系统里,对象构造失败是必须要处理的问题,失败的原因中最常见的则是内存不足(实际上这也是对PC平台的要求,但是在实际中往往忽略,因为内存实在便宜)。两段式构造就是一种常用而有效的设计。举例来说:
CMySimpleClass:
class CMySimpleClass
{
public:
CMySimpleClass();
~CMySimpleClass();
...
private:
int SomeData;
};
CMyCompoundClass:
class CMyCompoundClass
{
public:
CMyCompoundClass();
~CMyCompoundClass();
...
private:
CMySimpleClass* iSimpleClass;
};
在CMyCompoundClass的构造函数里初始化iSimpleClass对象。
CMyCompoundClass::CMyCompoundClass()
{
iSimpleClass = new CMySimpleClass;
}
当创建CMyCompoundClass的时候会发生什么呢?
CMyCompoundClass* myCompoundClass = new CMyCompoundClass;
为CMyCompoundClass的对象分配内存
调用CMyCompoundClass对象的构造函数
在构造函数中创建一个CMySimpleClass的实例
构造函数结束返回
一切看起来都很简单,但是如果第三步创建CMySimpleClass对象的时候发生内存不足的错误怎么办呢?构造函数无法返回任何错误信息以提示调用者构造没有成功。调用者于是获得了一个指向CMyCompoundClass的指针,但是这个对象并没有构造完整。
如果在构造函数中抛出异常会怎么样呢?这是个著名的噩梦,因为析构函数不会被调用,在创建CMySimpleClass对象之前如果分配了资源就会泄露。关于在构造函数中抛出异常可以单讲一个小时,但是有一个建议是:尽量避免在构造函数中抛出异常。
所以,使用两段式构造法是一个更好的选择。简单的说,就是在构造函数避免任何可能产生错误的动作,比如分配内存,而把这些动作放在构造完成之后,调用另一个函数。比如: