Symbian3/SDK/Source/GUID-AF2CE612-F12E-5A18-81A5-C303992D2D46.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Tue, 20 Jul 2010 12:00:49 +0100
changeset 13 48780e181b38
parent 7 51a74ef9ed63
permissions -rw-r--r--
Week 28 contribution of SDK documentation content. See release notes for details. Fixes bugs Bug 1897 and Bug 1522.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-AF2CE612-F12E-5A18-81A5-C303992D2D46" xml:lang="en"><title>Possible
Problems</title><prolog><metadata><keywords/></metadata></prolog><conbody>
<p>This section describes the possible problems that you may encounter when
you develop applications or libraries on the Symbian platform
based on Standard C++. These problems can occur in the following scenarios: </p>
<ul>
<li id="GUID-A3F0DCD7-CA38-5405-B01D-1E3B3F75B67D"><p><xref href="GUID-AF2CE612-F12E-5A18-81A5-C303992D2D46.dita#GUID-AF2CE612-F12E-5A18-81A5-C303992D2D46/GUID-39350E32-26C2-5440-B221-10EE693CCF18">Use of operator new</xref>  </p> </li>
<li id="GUID-9B185254-36B9-58F7-888D-8198EAD77769"><p><xref href="GUID-AF2CE612-F12E-5A18-81A5-C303992D2D46.dita#GUID-AF2CE612-F12E-5A18-81A5-C303992D2D46/GUID-A85386B3-3E37-5303-8FBF-211551D5CB71">Use of one definition rule</xref>  </p> </li>
<li id="GUID-01A440D6-7E35-5F4E-8E1E-F5877F3967F2"><p><xref href="GUID-AF2CE612-F12E-5A18-81A5-C303992D2D46.dita#GUID-AF2CE612-F12E-5A18-81A5-C303992D2D46/GUID-6CE49D59-46BB-5145-B346-6FD3EA8BC011"> Standard C++ calling Symbian C++ functions </xref>  </p> </li>
</ul>
<section id="GUID-39350E32-26C2-5440-B221-10EE693CCF18"><title> Use of operator
new()</title> <p>The function signatures of the global <codeph>operator new</codeph> on
Symbian C++ and Standard C++ differ only in the exception specification. As
per Standard C++, global <codeph>operator new</codeph> has the following signature: </p> <codeblock id="GUID-4369105F-C969-54E1-BBE5-C14ECA239F83" xml:space="preserve">void* operator new(std::size_t size) throw(std::bad_alloc);</codeblock> <p>While
in Symbian C++, it is: </p> <codeblock id="GUID-9FCCB90D-3E2D-505B-8FC9-6E0FACAC09F3" xml:space="preserve">void* operator new(unsigned int aSize) throw();</codeblock> <p>Since the compiler name-mangles references to both these symbols as the same,
it is possible (for the linker) to resolve a reference to one with the definition
to the other. If such a combination is not identified at build time, the memory
allocation may fail in the following cases: </p> <ol id="GUID-C6D4BDDD-B981-519C-9F2C-35DA294A23D9">
<li id="GUID-FFD5DB62-462F-5A4A-BC51-DBE213B9BD0F"><p>If a reference to Symbian
C++ <codeph>operator new</codeph> is resolved against the definition of Standard
C++ <codeph>operator new</codeph>, then it throws an exception which may leave
the <codeph>CleanupStack</codeph> in an unstable state. </p> </li>
<li id="GUID-19A3119A-E882-5C17-9674-9B45D6307FFE"><p>If a reference to Standard
C++ <codeph>operator new</codeph> is resolved against the definition of Symbian
C++ <codeph>operator new</codeph>, then the <codeph>operator new</codeph> returns <b>NULL</b> (while
an exception was expected). Since the return is not checked by the compiler,
it may cause a bus error. </p> </li>
</ol> <p>So, the declarations must be kept separate in the translation unit.
In this case only one of them can appear in a translation unit. Also, since
they have the same mangled names, they cannot appear in the same link unit. </p> </section>
<section id="GUID-A85386B3-3E37-5303-8FBF-211551D5CB71"><title>Use of one
definition rule</title> <p>As per Standard C++, one definition rule (ODR)
says that there must be only one definition of a symbol in a program. But
to be able to maintain a single definition in a program, symbol pre-emption
must be possible. This functionality is not supported on the DLL model of
the Symbian platform. </p> <p><b>Example</b> </p> <p>The following example
illustrates the problem with the use of one definition rule: </p> <codeblock id="GUID-FB9FBAAD-8CB8-5EAB-BA25-18A92822CF8E" xml:space="preserve">//MySingleton.h
template &lt;class T&gt;
class MySingleton
    {
    public:
    static T&amp; GetInstance()
        {
        static T * aT = NULL;
        if (!aT) aT = new T;
        return *aT;
        }
    };
class X: public MySingleton&lt;X&gt;
    {
    public:
    X(): iX(0) {};
    int Prod()
        {
        return ++iX;
        }
    private:
    int iX;
    };</codeblock> <p> <b>Foo.cpp</b>  </p> <codeblock id="GUID-3AFCAE2C-8028-5813-BED1-889AD2909302" xml:space="preserve">#include &lt;MySingleton.h&gt;
EXPORT_C int Foo()
    {
    return X::GetInstance().Prod();
    }</codeblock> <p> <b>Bar.cpp</b>  </p> <codeblock id="GUID-6C00938A-2CD5-58D8-B937-6EE73C5BF483" xml:space="preserve">#include &lt;MySingleton.h&gt;
EXPORT_C int Bar()
    {
    return X::GetInstance().Prod();
    }</codeblock> <p>In a scenario where <filepath>Foo.cpp</filepath> is in <filepath>Foo.dll</filepath> and <filepath>Bar.cpp</filepath> is
in <filepath>Bar.dll.</filepath> To call <codeph>Foo</codeph> and <codeph>Bar</codeph> from
an application: </p> <codeblock id="GUID-E4A0FA6F-9792-5052-80B5-2372EB53FBFA" xml:space="preserve">int Baz()
    {
    return Foo() + Bar();
    }
int E32Main()
    {
    printf("%d\n", Baz());
    }</codeblock> <p>This example must have displayed the output as <b>1,
2</b>. But on the Symbian platform, it displays <b>1,1</b>. </p> <p>The problem
here is, the Symbian platform's DLL model. In particular, the Symbian platform
does not support symbol pre-emption. <codeph>static T * aT</codeph> gets allocated
in each DLL in which <codeph>X::GetInstance</codeph> is invoked. Here the
problem arises because the Symbian platform cannot redirect the references
in distinct DLLs to a single unique location as required by the ODR. </p> </section>
<section id="GUID-6CE49D59-46BB-5145-B346-6FD3EA8BC011"><title>Standard C++
calling Symbian C++ functions</title> <p>The following example illustrates
the nature of one of the problems associated with achieving <i>seamless</i> integration
of Standard C++ with Symbian C++. Here <i>seamless</i> means: without the
manual introduction of additional harness or barrier code to effect the integration. </p> <p> <codeph>SymbianCallerLC</codeph> calls
two different functions: </p> <ul>
<li id="GUID-CC89E765-AF86-5300-BB76-F84DCF9E3910"><p>one which expects standard
C++ semantics (<codeph>CppCallee</codeph>), and </p> </li>
<li id="GUID-2E9D21A4-8FD3-5DC9-A264-7E7FEA05F4A9"><p>another which expects
the Symbian platform semantics (<codeph>GetAK1LC</codeph>). </p> </li>
</ul> <p> <codeph>SymbianCallerLC</codeph> itself belongs to the Symbian C++
world since it participates in the LC convention (it imposes a contract on
its caller with respect to the object that it returns). </p> <codeblock id="GUID-D88FA0A6-1107-570D-B79A-30EA10E4AB0C" xml:space="preserve">K1 * SymbianCallerLC()
    {
    K1 * aK1 = GetAK1LC();
    CppCallee(aK1);
    return aK1;
    }</codeblock> <p>The sole point of this function is to demonstrate that <i>stack
depth</i> cannot be used as an implicit means to synchronize the cleanup stack
with the control stack. It might be thought that recording <i>stack depth</i> at
the point at which an object is pushed onto the cleanup stack can be used
by the runtime to determine if the object should be <i>popped and destroyed</i> during
a standard C++ <i>throw</i>. Such a belief would be erroneous. For example,
a stack allocated object of sufficient size (<codeph>aArray</codeph> in this
case). The <i>stack depth</i> when the object allocated by <codeph>K1::NewLC</codeph> is
pushed on the cleanup stack is bound to be greater than the <i>stack depth</i> when
the <codeph>try</codeph> statement is executed in <codeph>CppCallee</codeph>.
From this example, therefore, that the <i>stack depth</i> at which an object
was allocated (or rather pushed onto the cleanup stack) gives no indication
of the ordering of various operations and can therefore not be used to determine
the inclusion of one extent within another. </p> <codeblock id="GUID-4FD53631-1369-5833-B0C0-1FD4F3C28BFB" xml:space="preserve">K1 * GetAK1LC()
    {
    int aArray[100]; 
    // stack frame for GetAK1LC has space for 100 ints - i.e. sp in this call to K1::NewLC 
    // will be less than at the 'try' in CppCallee
    return K1::NewLC(aArray);
    }</codeblock> <p>In the current context the object returned by <codeph>GetAnotherK1LC</codeph> will
be pushed on the cleanup stack when stack depth is less than it was in the
earlier call to <codeph>GetAK1LC</codeph>, more evidence that stack depth
cannot be used to determine ordering or extent inclusion. </p> <codeblock id="GUID-798CD3AA-0E08-5641-9FDA-DCE5224C7457" xml:space="preserve">K1 * GetAnotherK1LC()
    {
    return K1::NewLC();
    }</codeblock> <p> <codeph> CppCallee(K1 * aK1)</codeph> is a <i>catcher</i> which
calls <codeph>CppCallee(K1 * aK1, K1 aK2)</codeph> which can throw. It also
calls <codeph>GetAnotherK1LC()</codeph> in the extent of the <codeph>try</codeph> statement.
If <codeph>CppCallee(K1 * aK1, K1 aK2)</codeph> throws it might seem desirable
that <codeph>anotherK1</codeph> must be cleaned up by the runtime as part
of the throw. </p> <codeblock id="GUID-EAB8D25C-F8C4-5CF1-8AE4-5BEE7A877567" xml:space="preserve">void CppCallee(K1 * aK1)
    {
    try 
        {
        K1 * anotherK1 = NULL;
        anotherK1 = GetAnotherK1LC();
        CppCallee(aK1, anotherK1);
        }
    catch (...)
        {
        }
    }</codeblock> </section>
</conbody><related-links>
<link href="GUID-D6BEAF0D-844D-51F4-8DB7-FB1D60E17FE3.dita"><linktext>Copyright
Acknowledgments for Standard C++ (STLport)</linktext></link>
<link href="GUID-F7FEB759-E64D-5B6D-9017-C5E982E4FC16.dita"><linktext>Standard
C++ Library Overview</linktext></link>
<link href="GUID-2CCD1748-9EDE-5383-9941-A3051E06F3E2.dita"><linktext>Standard
C++ Support on the Symbian Platform</linktext></link>
<link href="GUID-1ACD01D1-2055-581A-9478-2C0D7D1CF9E6.dita"><linktext>Use Cases
for Writing Standard C++ Code</linktext></link>
<link href="GUID-E331B72B-84AF-558A-9B8F-73E5E50B58C7.dita"><linktext>Building
a Standard C++ Application or Library</linktext></link>
<link href="GUID-D32E52C9-F05C-5F1E-8B49-243D555C353C.dita"><linktext>Known Issues</linktext>
</link>
<link href="GUID-5B3F5296-D6D0-5D25-8362-141DF5927E52.dita"><linktext>Troubleshooting</linktext>
</link>
</related-links></concept>