How I found interesting things about C and C++ languages while learning Symbian C++

It is interesting to see that while reading Symbian C++ code you discover things related to C or C++ language that are not quite the same as you already knew them.
Due to the limitations that a smart-phone has (mostly in terms of power consumption which, from a software perspective, translates into number of CPU cycles required to do something, and in terms of memory size), its corresponding software has to tackle in a very accurate manner some aspects which could be neglected by a PC desktop programmer.

I remember that while browsing a Symbian documentation I read somewhere that:


C++ introduces a memory overhead compared to C (a program compiled in C++ will be bigger than one compiled in C), so if you decide for writing an operating system in C++ you have to be more careful than when writing in C.

One thing which kept my attention when having first contact with Symbian was the fact that you should always use the appropriate data types. This was not very surprising for me taking into account that I have an embedded programming background and I know that I have to be very careful when using unsigned int and when int.
But this is not everything. Symbian even has dedicated typedef’ed data types for each C built-in type (except char and void), and it is strongly recommended to use those instead of C types.

While looking at some examples in Symbian C++ other strange things, like inline constructors, private copy-constructors, private static methods, overloading the new operator with new(ELeave), macros like TRAP and TRAPD, popped into my attention and revealed hidden aspects of C++ language.

Generally if you know C++ it would be quite simple to start writing software for Symbian smartphones. But if this is true, why I read everywhere about the steep Symbian learning curve?


For sure if you have a C++ background it would be simpler for you to learn Symbian C++ than if you don’t know anything about C++, but you have to be aware that you will have to spend some effort in this learning phase.

An aspect which I would like to approach in more detail in this post is the one related to descriptors. I would like to stress more the difference between how some things are handled in Symbian C++ and in standard C++.

Before starting let me tell you a thing which I did not know until several days ago: Symbian holds a patent for descriptors and you can find about it here.

This discussion must start with one basic question: how should a programming language represent a sequence of characters?
Obviously there is a lot of programming using some other data types than plain binary numbers. Reading files, or reading input characters from the keyboard, writing into files are just few examples when you’ll need to work with character data types.
There are two ways a programming language can handle this: it stores the length of the string within the string itself or it can use a magic terminator character (or a sentinel) like NUL character (‘’).

I read it somewhere something like a maxima:

There is no “right” way to implement strings.

And this could be indeed true … both alternatives have advantages and disadvantages.

Coming back to the comparaison between Symbian C++ and standard C++ (an also standard C, after all C++ inherits the way strings are handled in C) one big advantage on Symabian C++ side is that UNICODE characters can be stored in descriptors, which is not the case for C++ Strings and C plain character arrays.

C uses the NUL character to flag the end of a string and C++ inherits this approach, but it adds also the String class which contains methods for string-manipulation and avoids somehow the complications that end-of-string character may induce. In both implementations, the one with the string-terminator and the one with String class, only ASCII characters can be represented. This means that if you would like to write a piece of code processing a Japanese character, or a Hebrew one, you are bounded by this feature.
By the way … how are those handled? I suppose there are many situations in which the program must process such characters, especially in web programming.

Descriptors come into two flavors: 8-bit which can store ASCII or binary data, and 16-bit which can store in addition UNICODE characters.

In fact, the major issue is not that C relies on the string-terminator character, but it is the bad practice surrounding it which is the evil.

C++ implements the String class which gives programmer the freedom to dynamically change the string length, to append or to cut it, even some operators are overloaded inside String class to simplify string processing, depending on his (my apologies for women programmers) wish. Basically this gives the possibility to create un-limited strings, but all of this at a cost. The string is stored on the heap using some code like the one below:


char *s = new char[string_size];

delete[]s;

This has the drawback that no bounds checking are performed on the string. There is no MaxLength() method, like it is in TDes class, which is part of Symbian descriptors inheritance tree. Using this C++ style on a memory limited environment like a smartphone, is a very risky attempt. As far as I’ve seen buffer overflows are a critical part in Symbian and it are not tolerated, even this should come at another cost (increasing language complexity). Actually this is the driving reason that descriptors were implemented to take place of character arrays: they have to be in complete control of their length, maybe on PC desktops buffers overruns are sometimes acceptable, but on a smartphone this is strictly forbidden.

Everything that consumes memory, or which can lead to this, in an unnecessary manner, is treated as an evil.

It is also the case of the complete mechanism handling leave functions that I discussed some times ago. The most critical thing in case a leave may occur, is that memory is orphaned, creating memory leaks.

The way in which descriptors are passed as parameters is done smarter than in standard C++. The programmer is strongly to encouraged to use references to abstract base classes, TDesC and TDes , when passing descriptors as parameters. The caller of a function does not need to know necessarily which type of descriptor is allowed as parameter. What matters is that the caller should know what methods can be called on it, and TDesC and TDes provide generic methods for manipulating any kind of descriptor. It would be complicated to let the function require a certain type of parameter, because the implementation of the function will be bounded to a certain type of descriptor. Also if the function will be part of an API, the clients using that API won’t have the flexibility to use whatever descriptor type they want.

Taking TDesC and TDes references as function parameters solves the possible issues that might be introduced by this etherogenuos string approach that exists in Symbian (specialized, different-size descriptors). The fact that many different length descriptors exist may introduce problems when implementing a function accepting a certain type of descriptor and calling it with another.

In fact TDesC and TDes have the smallest size (just 8 bytes) among all descriptors and are the most suitable candidates to be passed on the stack (remember that Symbian is very restrictive with variables passed on the stack – you’re not allowed to statically create complex objects like instances of C classes).

Hope you had a nice lecture, talk to you more about Symbian in future posts.

Advertisements

One Response to How I found interesting things about C and C++ languages while learning Symbian C++

  1. kellogs says:

    May I know why in the world have you chosen to undertake symbian as the next platform to code for ?

    It has that awful steep learning curve you were talking about because:

    – awful documentation adjoining SDKs
    – inability to test trivial things just on the emulator – i.e. it took me *hours* to realize that my implementation of autostart and distinction from application launch scenarios (autostart on installation / boot and start by click) was working just fine. Just not on the emulator; i.e.2 – you cant expect to dynamically obtain the path of your program, strip the ‘program.exe’ part, append ‘file.txt’ and be able to create the file on emulator – while this works on device. Why ? because the program gets installed on the so called ‘ROM’ memory of an emulator – which is read only; etc etc etc. So many changes that need to be done to the same code just to run it on emulator vs. device. The more code the more changes.
    – emulator often crashes during startup in non-debug mode;
    – the perl build system sometimes fails to produce binary code; sometimes right after fresh IDE installation;
    – APIs do not behave like they should; i.e. write something into an RFile and attempt toRFile::read() it back from it – most of the times the first character from the file is not read, and often some of the last characters will also be missing. Solution – RWriteFileStream and RReadFileStream, which are themselves very hard to use correctly;
    – installer and on device debugging are a mess when combined with online signing; sometimes you get ‘access not granted’ alhoug it should be granted (during installation), sometimes you will want to debug an online signed version of the app on the device – have fun with that. Other times the on-device debugging won’t work until an IDE restart has occurred.
    – the whole signing process is extremely time consuming and also limiting the apps you can create. It is all a hassle unless you reach for your pocket and free it of 200$ yearly;
    – we get different behaviour of the same code on different devices belonging to the same edition of S60 (I have noticed discrepancies among S60 3rd non-FP vs. FP1 / FP2);
    – user interfae design and use is just a pain in the ***; I have never seen such a badly written UI framework. Take SettingsItemLists for example. Where you would have expected to encounter 3 classes for the MVC pattern you will actually have to deal with 5 classes, having the methods chaotically spread between them. Oh and don’t expect do manage skinning your UI controls all in the same way. Some of them support skinning while others do not (like CEikLabel). So you will have a nice background fr the most of your UI, except for a few labels :). And do not expect for a CEikLabel to be made multiline if put onto a CAknForm. The CAknForm barely recognized it in the first plae. Worked fine in some CEikView or something similar;
    – all kind of reminiscences from early nineties like the ‘epoc’ naming conventions, Avkon, Uikon and Eikon windowing frameworks coexistence, no proper exception mechanisms due to inability of the formerly used ARM5 compiler from Realview, etc.
    – as you have noticed, client/server architecture is unable to guarantee a certain timing of client requests responses. So, If I am desperately interested in catching right soft key before a call has connected, tough luck. It came only after the call connected no matter how badly I have tackled with priorities of active objects involved.

    I could go on and on. The point is that the learning curve you were mentioning is not at all related to descriptors or active objects, but rather to the above.
    Don’t loose it over the ‘oh so limited power and memory’ nonsense the internet keep throwing at developers from early nineties, now we have Androids at 1 GHz and 512 RAM. And Badas. And iPhones. And, cross my heart, Symbians. Yes, Symbians are no longer the constrained devices they once were. Think about all the addons symbian posses nowadays. Qt. Python. Flash. Web runtime. J2ME. All with the one reason of somehow avoiding the ‘tough c++’ learning curve. Result – symbian is no less shitty than it was. Bad guess, that learning curve was not there due to c++, but to the awful design and implementation of this hag OS, lack of documentation, lack of proper tools and all the ‘partnering programs’ that only a company could put up with.

    Good thing they have started to come into their senses (or should I say better they were put back to their place) because of competition which emerged 2-3 years ago.
    Now we have good wiki and forums, API plugins unconstrained from the partnering programs, open online signing (for free)… however, in my opinion, they still are a veeeery long way from catching up the others. They are not dead just yet, but I do not see a better future for them.

    So, may I now know why have you undertaken symbian development ?

    As for me – I have done it for the $$. I had to survive on something and this is what came along.

    Good luck to all

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: