The Symbian OS architecture does not allow DLLs to have a data segment (static data, either initialized or uninitialized). There are problems with deciding what such a data segment would mean:
Do all users of the DLL share it?
Should it be copied for each process that attaches to the DLL?
In addition, there are significant run-time overheads in implementing any of the possible answers.
However, because the WINS/WINSCW emulator uses
the underlying Windows DLL mechanisms, it can provide per-process DLL data
using "copy-on-write" semantics. This is why the problem goes undetected until
the code is built for an actual Symbian OS device.
Consider this section of C++ code, added to a file QSORT.CPP, which
is part of ESTLIB.DLL
// variables
struct div_t uninitialised1; // in .DATA
static struct div_t uninitialised2; // in .BSS
struct div_t initialised1 = {1,1};// in .DATA
static struct div_t initialised2 = {2,2};// in .DATA
// constants
const struct div_t const1 = {3,3};
const static struct div_t const2 = {4,4};
const TPoint none(-1,-1);
static const TText* plpPduName[12] =
{
_S("Invalid"),
_S("DataFlowOff"),
_S("DataFlowOn"),
_S("ConnectRequest"),
_S("ConnectResponse"),
_S("ChannelClose"),
_S("Info"),
_S("ChannelDisconnect"),
_S("End"),
_S("Delta"),
_S("EndOfWrite"),
_S("PartialWrite")
};
When this code is built, the messages from PETRAN look something like:
PETRAN - PE file preprocessor V01.00 (Build 170) WARNING: Dll 'ESTLIB[10003B0B].DLL' has initialised data. WARNING: Dll 'ESTLIB[100002C3].DLL' has uninitialised data.
The associated .map file contains information that
helps to track down the source file involved.
Look in Symbian OS\release\arm4\urel\dllname.map
Search for .data or .bss
In this example, we find:
.data 0x10017000 0x200
0x10017000 __data_start__=.
*(.data)
.data 0x10017000 0x40 ..\..\Symbian OS\BUILD\STDLIB\BMMP\ESTLIB\ARM4\UREL\ESTLIB.in(QSORT.o)
0x10017000 initialised1
*(.data2)
*(SORT(.data$*))
0x10017040 __data_end__=.
*(.data_cygwin_nocopy)
.bss 0x10018000 0x18
0x10018000 __bss_start__=.
*(.bss)
.bss 0x10018000 0x18 ..\..\Symbian OS\BUILD\STDLIB\BMMP\ESTLIB\ARM4\UREL\ESTLIB.in(QSORT.o)
0x10018008 uninitialised1
*(COMMON)
0x10018018 __bss_end__=.
So the DLL has 0 x 18 bytes of uninitialized data (.bss)
and 0 x 40 bytes of initialized data (.data), all of
which comes from qsort.o
The variables initialised1 and uninitialised1 both
have global scope, so the .map file lists them by name
(and puts them both in the initialized data). The static variables do not
get named in the .map file.
Removing the first four lines of code shown above leaves just variables
that are declared as const, but only reduces .bss to 0x08 bytes,
and .data to 0x30 bytes. There are
two problems remaining:
Declaring
C++ objects as const does not help if they have a constructor.
The 8 bytes of uninitialized data are allocated to hold the TPoint object,
but it will not become const until after the constructor
has completed.
The declaration const
TText* says that the TText values may not
be altered, but it does not make the pointer a constant as well. The 48 bytes
of initialized data are the 12 pointers in the plpPduName array.
To make the pointers constant as well as the values they point to, the declaration
needs an additional const after the TText*
static const TText* const plpPduName[12] =
{
_S("Invalid"),
_S("DataFlowOff"),
_S("DataFlowOn"),
_S("ConnectRequest"),
_S("ConnectResponse"),
_S("ChannelClose"),
_S("Info"),
_S("ChannelDisconnect"),
_S("End"),
_S("Delta"),
_S("EndOfWrite"), _S("PartialWrite")
};
Removing the TPoint global variable and adding
the extra const to the plpPduName array
finally removes the last of the offending .bss and .data