As one of the core developers of the libsxe open source library, I thought I’d write a blog post explaining our choice of C for the library. We eliminated interpreted languages, including java, based on the requirement to be able to run in an embedded environment like the kernel. This left two choices: C and C++.
The decision to use C rather than C++ is often questioned by those new to software development. C++ is a newer, object oriented language. Why wouldn’t one use it when developing a new library? There are some historical reasons why C was chosen as the programming language for libsxe. A previous library that two of the libsxe developers worked on needed to be embedded in the FreeBSD kernel, where C was a requirement, and we felt that we might run into similar requirements. However, the main reason we avoided C++ is the problems that come with it.
While the Resource Allocation Is Initialization (RAII) pattern in C++ claims to make resource deallocation failsafe, its disciplined application is problematic. Many C++ applications we have worked with seem to be riddled with memory leaks. Memory allocation leads to another problem: indeterminism. As the load on a library or service increases, its allocates additional resources and expands its memory footprint. At some point, this may push it into a configuration that fails to perform as expected. Embedded systems avoid this problem by configuring the system and testing it’s performance at the maximum capacity. All resources are allocated at initialization. Unfortunately, C++ hashes, strings and container implicitly use incremental allocation, offering little or no ability to preallocate space, making a dynamic memory footprint almost certain.
Like memory allocation, multi-threading is a major cause of bugs. Even one tiny segment of code that is executed in two thread contexts can lead to bugs that are nearly impossible to spot and very difficult to debug. While C++ doesn’t require programmers to use multiple threads, many of its libraries build in thread safety, and C++ programmers seem more likely to charge in to a multi-threaded implementation than C programmers.
The worst problem with C++ is how easy it makes writing impenetrable code. Operator overloading, member function names duplicated between classes, virtual functions, templates, automatically generated constructors and destructors, and exception handling all make it less easy to look at a piece of C++ code and see what it is doing. Inappropriate overuse of object orientation and patterns also adds unneeded complexity. Object orientation is a power tool that should be used when needed, and not used unless needed.
Is C the right choice? It has its drawbacks. Our function names can get very long. We end up doing some funky stuff with the C preprocessor. But, overall, it gives us most of the features we want, without the drawbacks of C++.