现在的位置: 首页 > 综合 > 正文

ARM平台独有问题 Writable Static Data in DLLs

2013年07月16日 ⁄ 综合 ⁄ 共 2005字 ⁄ 字号 评论关闭
 
[S60] ARM平台独有问题 Writable Static Data in DLLs
2007-07-08 16:59
在编译arm平台程序的时候,出现如下错误提示:
ERROR: Dll 'AppName[UID].APP' has initialised data.
或者:
ERROR: Dll 'AppName[UID].APP' has uninitialised data.
(扩展名APP的应用程序其实也是一个DLL。)

而在为模拟器编译的时候,这个问题不会出现。这曾经导致我在完成完整的设计,编码和调试后,
被迫放弃原有设计。

从这条错误信息的字面意思是什么也看不出来的。initialised 和 uninitialised都一样有问题。
其实真正的含义是Dll里存在可写的全局变量。

大家知道在程序运行的时候,DLL只会被装载一次。在Windows平台,每个进程都有自己独立的DLL空间。也就是说,不同进程装载同一个DLL,互相之间是独立的。只有在一个进程内,才是共享的。但是S60平台的设计是所有进程都共享同一个DLL空间。这样的设计显然是出于节约内存的目的,是很有必要的。但是这样就带来一个问题,那就是DLL里不可以有可写的全局变量,否则就要造成混乱。A进程对变量的改写会直接影响到B进程,这是程序设计者所不愿意看到的。所以,S60平台的编译器就禁止了在DLL内申明可写全局变量。但是全局变量还是可以用的,只要加上const申明即可。

一般来说,在做DLL设计的时候,的确不鼓励使用可写全局变量。即使是windows平台,DLL的可写全局变量也会在不同模块之间带来问题。当遇到这个编译器错误的时候,应该设法修改设计,回避使用全局变量。

但是因为APP实际上也是DLL,这就导致连S60的主程序也不能使用可写的全局变量,这个在某些时候就成了问题,全局变量毕竟是一个重要的实现手段。对此,S60提供了线程局部存储(thread local storage)来解决问题。
TLS的关键是两个函数:
void Dll::SetTls(void*)和void* Dll::Tls()
SetTls用于将任意类型的指针保存到线程局部存储中,而Tls()则取出该指针。
指针指向在堆上分配的一块内存。一个线程只能有一个局部存储变量。所以,如果你有很多全局变量,就要定义一个结构,把所有的全局变量封装在其中。这是挺别扭的,不过S60 3rd据说就支持dll的可写全局变量了。

tls样例代码:

设置
GlobalData* p = new GlobalData();
if ( p )
{
   Dll::SetTls( p );
}

使用
GlobalData* p = (GlobalData*) Dll::Tls();

 

 

补充:

 

可写静态数据

全局可写静态数据(Global Writeable Static Data,WSD)就是在整个进程的生命周期内都存在的预处理变量。有时候我们需要WSD定义变量给其他的文件使用。这种情况时常发生在将非Symbian操作系统环境的代码移植到Symbian系统中来的时候。

 

EKA1上的WSD

在Symbian系统版本6.1, 7.0, 7.0s, 8.0a, 8.1a的内核架构EKA1中,仅仅在EXE类型的程序中支持WSD。我们不能在DLL和APP中使用WSD,如果我们进行了这样的定义,编译器会报告"初始化数据" 错误信息。

在EKA1中,我们如果要使用WSD的话,有下面这些解决办法:

(1), 使用本地线程存储(TLS,Thread Local Storage)。 在Symbian的FAQ和技术技巧里面有例子关于怎么用TLS来定义WSD。
(2), 将全局变量变成类成员变量。这个方法有很大的工作量,尤其是WSD在很多不同地方被使用的情况下。
(3), 使用ECompXL。尽管ECompXL是被用来压缩Symbian系统的可执行程序文件的,但是他的一个"副作用"可以让开发者把它用来当作WSD使用。

EKA2上的WSD

在Symbian系统版本8.0b, 8.1b及其版本9以后的内核中,EXE和DLL都支持使用WSD。不过尽管如此,在DLL中使用WSD仍然需要作一些小的修改, 需要在MMP文件中添加如下宏定义:

EPOCALLOWDLLDATA

不过,这是有代价的。当在EKA2上使用WSD的时候需要仔细考虑以下列出的情况:

(1) EKA2的模拟器上仅仅允许有WSD的DLL被一个进程装载(最近做的项目中就遇到了这个问题,一个有WSD的DLL被两个exe调用导致这个两个exe不能相互调转切换,提示feature
not supported, 呵呵~~)

(2) WSD数据块占用RAM空间

(3) 在ARMv5上块是一种有限的资源

(4) 一个进程中有WSD的DLL的数目是受限的。

 

抱歉!评论已关闭.