RSS

Search Engine

Wednesday, May 26, 2010

Do's and Dont's of Symbian programming

Here below are given a few example of good practices to follow and practices to avoid while programming in Symbian.

  • Always use the correct data type which suites the requirement. This is not specific to programming in Symbian OS. It is always a good parctice to use correct data types. Using incorrect data type can sometimes lead to bugs which are very hard to bust.
    eg:

    void SomeFuntion()
    {
    TUint theValue(0);
    TInt error = GetValueOfSomething(theValue); //Some method that assigns the value to "theValue" (GetValueOfSomething(TUint& aValue))
    if(error != KErrNone)
    return;

    for(TInt i=0; i


    The same thing can happen if the data being compared are of different types.It is always a good practice to use correct data type or typecast them.


  • Use "Mem::Copy()" instead of "memcpy()" while copying data in memory. The method "Mem::Copy()" is heavily optimized. It is about three times faster than memcpy() for unaligned memory copies.
    It is, most of the time, better to use the Symbian OS library provided string and memory API's than using own implementation. Since most of the API provided by Symbian are optimized, the own implementation may not be as fast as Symbian provided implementation.

  • Always push the heap allocated data onto CleanUpStack before doing any operation that can leave. This avoids memory leaks, incase the operation leaves.

  • Avoid cyclic dependencies between two server modules. Eg:

    Two servers S and S'. S is client of S' and S' is client of S.
    S sends a synchronous message M to S' and S' sends synchrounous message M' to S and completes M only after completion of M'.


    This kind of scenario can lead to a deadlock.

  • TRequestStatus instance passed to service provider must have greater lifetime than asynchronous operation. A very common bug is TRequestStatus allocated on stack. Eg:

    void CMyRequest::DoSomeThingAsync()
    {
    //Some pre-amble operations...
    //
    //
    TRequestStatus status = SendRequest();
    //Some code...
    User::WaitForRequest(status); //This will cause problem
    //some more code...
    }

    TRequestStatus CMyRequest::SendRequest()
    {
    switch(iMyState)
    {
    case 1:
    {
    TRequestStatus status1;
    iServiceProvider->Service1(status1); // This will cause problem
    return status1;
    break;
    }
    case 2:
    {
    TRequestStatus status2;
    iServiceProvider->Service2(status2); // This will cause problem
    return status2;
    break;
    }
    case 3:
    {
    TRequestStatus status3;
    iServiceProvider->Service3(status3); // This will cause problem
    return status3;
    break;
    }
    }
    TRequestStatus dummy; // To remove compiler warning
    return dummy;
    }

  • In order to have a robust program, it is always a good practice to check the return values of all called function. All the pointers being used should be checked against NULL before dereferencing.

  • When using interfaces (pointer to some class-object) created by other object always make sure who owns the interface, and whose responsibility to destroy it. eg:
    CMdaAudioOutputStream::CustomInterface(TUid aInterfaceId); //returns TAny*
    In this case it is the responsibility of the caller to destroy the interface after using it.

0 comments:

Post a Comment