DLL contains uninitialised data - this wasn't a problem on WINS

Question:

PETRAN warns me that my DLL contains uninitialised data - this wasn't a problem on WINS. How do I track down this uninitialised data and why is it a problem on ARM4 but not WINS?

Answer:

The Symbian OS architecture does not allow DLLs to have a data segment (initialised or uninitialised). There are problems with deciding quite what such a data segment would mean (Is it shared by all users of the DLL? Should it be copied for each process which attaches to the DLL?) and significant runtime overheads in implementing any of the possible answers. EPOC32 does provides a mechanism whereby a DLL can manage private storage on a per-thread basis: see the description of the Dll class, in particular Dll::SetTls() and Dll::Tls().  

A WINS build uses the underlying Windows DLL mechanisms that can provide per-process DLL data using copy-on-write semantics: this is why the problem goes undetected until the code is built for target hardware.

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 which helps to track down the source file involved.
  • Look in epoc32/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 ../../EPOC32/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 ../../EPOC32/BUILD/STDLIB/BMMP/ESTLIB/ARM4/UREL/ESTLIB.in(QSORT.o)
    0x10018008 uninitialised1
    *(COMMON)
    0x10018018 __bss_end__=.

So the DLL has 0x18 bytes of uninitialised data (.BSS) and 0x40 bytes of initialised 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 initialised data). The static variables don't get named in the .MAP file.

Removing the first four lines of code shown above leaves just variables which are declared as "const", but only reduces the .BSS to 0x08 bytes and the .DATA to 0x30 bytes. There are two problems remaining:
  1. Declaring C++ objects as "const" doesn't help if they have a constructor. The 8 bytes of uninitialised data are allocated to hold the TPoint object, but it won't become "const" until after the constructor has been run.
  2. The declaration "const TText*" says that the TText values may not be altered, but it doesn't make the pointer a constant as well. The 48 bytes of initialised 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 and 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.

Further information on NewLC.com show you how to find out which particular variables in the source file are causing the problem.

Corresponding Instructions for ER3 and ER5

The GCC compiler used for ER3 and ER5 produces a different MAP file format.
  • Look in /Epoc32/Release/Marm/Rel/dllname.MAP
  • Search for "from *(.bss)", or "from *(.data)", both of which will be some way after "LINK EDITOR MEMORY MAP"

In the example, this finds:
  • .bss 10009580 10 0 2**2 alloc
    10009580 00000000 __bss_start__ =.
    from *(.bss)
    .bss 10009580 10 10 2**2 pe-arm-little [../../EPOC32/BUILD/STDLIB/MARMD/REL/ESTLIB.in]QSORT.o(overhead 4056 bytes)
    from *(COMMON)
    10009590 00000010 __bss_end__ =.


    .data 10009590 40 0 2**2 load alloc contents
    10009590 00000000 __data_start__ =.
    from *(.data)
    .data 10009590 40 40 2**2 pe-arm-little [../../EPOC32/BUILD/STDLIB/MARMD/REL/ESTLIB.in]QSORT.o(overhead 4056 bytes)
    10009590 initialised1
    100095a0 uninitialised1
    from *(.data2)
    100095d0 00000040 __data_end__ =.
    from *(.data$)

The explanation and analysis are the same as for Symbian OS v6.0 onwards.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值