C++ – Ensuring Robustness and Pointer Safety

c

I'm currently building a server responsible of storing and managing few million records of fairly complex and interconnected data. For reasons beyond my control the work has to be done with C++.

I have my concerns about error handling and especially pointer safety. Dereferencing a null pointer can cause the entire server to crash whereas in some – perhaps more suitable – languages you would get a null pointer exception which you can then handle. So, basically, a bug in handling of some rare corner case of a rare operation can bring the whole service down instead of just making one particular request to fail. Bugs are impossible to avoid so how can I ensure availability and robustness in such an environment?

Best Answer

Use C++11 (e.g. with GCC 4.9.1), not some earlier standard. Read more about memory leaks, smart pointers, buffer overflow, memory corruption, RAII.

If you follow several coding guidelines, notably the rule of three (which in C++11 is actually a rule of five), you would be able to write robust code. Use smart pointer templates like std::shared_ptr, std::unique_ptr and use standard STL containers. You should almost never use raw pointers like SomeClass* and ::operator new (if you want to use them directly, you are probably wrong, and you should always initialize them, often to nullptr; I believe that every variable should be explicitly initialized -the compiler would optimize useless initializations-, because that makes program behavior more reproductible.).

C++11 is a difficult language. Take several weeks to read several books about it, notably by B.Stroutrup: Programming -- Principles and Practice Using C++, a Tour of C++, The C++ programming language.

Be aware that C++11 is a different language than C (and even than its predecessor C++98). You need to take time to learn it. Look also inside the source code of several recent free software projects coded in C++.

Compile with all warnings and debug info (g++ -Wall -Wextra -g). Improve your code till you got no warnings. Make an exhaustive test suite. Use valgrind (on systems where it is available). Perhaps consider using frameworks like Poco, Boost, Qt. On production machine, use a watchdog.

BTW, you might learn more about Garbage Collection (see also the GC handbook), and notice that C++ favors reference counting, which can be viewed as a simple and limited form of GC (which is unfriendly to circular references).

You could also use operating system specific things (for Linux, read Advanced Linux Programming and signal(7)...) to catch some runtime errors. (I'm not sure it is a good idea to catch SIGSEGV, you'll need some very system & processor specific code; but it is doable).

Also, you could perhaps generate some of your C++ code (see also this). My MELT system is doing so (and you might also customize GCC with MELT to add some additional coding rules checking).

You seems very concerned about null pointer dereferences. If that scares you so much (it should not, since it is actually an easy bug to find; memory leaks are harder to find), you might craft your own smart pointer (above existing facilities) which would raise an exception in that case.

BTW, robustness of your code is much more related to the code size and the care and effort put in developing and testing it, than to the amount of data or records it has to process: a well crafted 30KLOC software able to handle 1000 records would probably be able to handle many dozens of millions of records, if given enough resources (notably computer power, disk, and RAM). A few millions of records does not feel scary (consider using Sqlite or Postgresql or Mongodb, etc, etc....).

Notice that some people are able to write very robust C or C++ code; in particular, many free software database management systems (Sqlite, Postgresql, Mongodb) are coded in C or C++ and are able to run for years, managing terabytes -or perhaps petabytes- of data. If possible, make your software published as free software (and develop it in the open): you'll get useful feedback from outside.