Software Reliability C++ vs Zig

A tiny comparison of C++ and Zig in terms of building reliable software

I have spent a lot of my life writing C++ code and if there has been one thing that has bothered me about C++ it is just how fragile it is and generally unhelpful in tracking down bugs.

I don’t have time for an exhaustive check here, so here is just the simplest example I could come up with to make a comparison. We are reading a file which doesn’t exist. In C++ we got:

When I run this it gives me absolutely no output. Nothing tells me the file was not there or that anything went wrong.

Let us look at the equivalent program in Zig:

If I run this I actually get a full stack backtrace:

I can actually easily jump in and look at the Zig standard library at where things went wrong, or just look at the message in the top which says file not found.

Now, some may argue that I only get this backtrace because I handled the error. Like I wrote try in front of cwd().openFile. Except Zig will not let not handle this potential error. If I remove the try I get:

This requires a bit explanation I am trying to do read from an object which is of type OpenError!File rather than just File. Basically I got a union type. It it sort of an optional, rather than being a value or null, it is an actual value or an error code. You got to deliberately unwrap the value before you can use it.

What if I forget to get the number of bytes read, and thus specify wrong range in buffer to print out?

Basically what happens if we remove the const size? Nope, Zig is not happy about that either:

Now to be honest I am not really a static typing fan. I prefer writing code in Julia, but dynamic languages at least tend to do quite rigid type checking at runtime and give you nice stack backtraces informing you what went wrong. Unless we speak JavaScript which seems to like to paper over every problem it encounters.

These stack backtraces in Zig actually impress me quite a lot since it is a pretty low level language and not a script language and yet we get these very informative stack backtraces. In fact I don’t get that nice backtrace in Julia or Python when I tried for this particular case.

Ok before finishing off let us do one more little comparison, as I just remembered one little thing I think is quite an embarrassment to C++:

I got this simple program where I forgot to write i < size and wrote just size instead where my condition was. Oops I got an infinitely running loop.

Here is the Zig version:

Just as you would expect this does not compile, instead we get:

And honestly this is how it should work. Most modern languages today will insist on a boolean type in your control-flow statements. Sure in the defense of C++, it tried to be backwards compatible with C, and things have advanced since then.

But it is still an interesting example of how a more modern and more type safe language can help you build quality software faster. Keep in mind a lot of this stuff is not unique to Zig. You could get a lot of these kinds of improvements by picking Rust, D, Swift or Go over C/C++. Zig however has a lot of the same low level functionality C programmers like, such as manual memory allocation and deallocation, a C friendly ABI so you can easily reuse all your existing C libraries.

Written by

Geek dad, living in Oslo, Norway with passion for UX, Julia programming, science, teaching, reading and writing.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store