No Future for Us to C

It has been a while since some official documents produced by the USA administration advised against using unsafe programming languages like C and C++ (yes, C and C++ are explicitly mentioned). Now, the news resurfaced on the web with an added deadline—manufacturers have until January 1, 2026, to create a memory-safe roadmap for existing applications.

Let’s have a look at the text:

Recommended action: Software manufacturers should build products in a manner that systematically prevents the introduction of memory safety vulnerabilities, such as by using a memory safe language or hardware capabilities that prevent memory safety vulnerabilities. Additionally, software manufacturers should publish a memory safety roadmap by January 1, 2026.

This is pretty strict, even if it is phrased with “should” and not “shall” or “must”. If you develop a new product, you’d better drop C or C++. Moreover, if you have an existing product written in one of these pesky languages, you should provide a roadmap to memory safety.

Being based in Europe it is only a temporary relief, eventually, something similar will come for the EU, because otherwise there would be too much of a competitive gap in product quality.

IMO C and C++ although eventually both boil down to unsafe memory access, are two different beasts with two different attitudes.

Let’s take C++, even if late (read in 2023), the committee started trying to address the memory safety concerns. They are designing a profile-oriented mechanism to constrain unsafe behavior (much like the rust approach). By using some utterly cumbersome syntax and semantics, you may eventually prove that a part of your code is memory-safe. Bad, ugly, and crappy (and late) as you want, but still (potentially) capable of fitting the requirement. I would also deem very interesting the cppfront approach that shifts the level, offering a memory-safe language that is translated into pretty-looking C++.

C is a whole different story. During its existence, C stood impervious to any advancement in the field. In its 50+ years of existence, it has almost remained unchanged. Its evolution focused on slightly refining existing syntax, rather than extending the language – it gained no OOP facility, no FP tool, and even no construct to handle modularity and component reuse1. C remained proudly low level over all its life, always strongly believing that programmers know what they do. Compared to any other popular language, C is unique in its stillness.

While the language existed, the world progressed – Object Orientation, Logic Programming, and Functional Programming explored new paradigms and new and more robust ways to write programs. Java first and Python later proved that you can write complex programs without juggling pointers and managing memory manually. But most of all, the size of program sources increased several orders of magnitude – the original Unix kernel was something less than 5kLoC of assembly code. Nowadays Linux kernel (without drivers) is 4MLoC. I expected a similar increase for other applications as well. In the same way, you can write huge websites with PHP (such as Wikipedia) you can still use C for writing a large codebase (Linux proves this), nonetheless C was designed for a simpler world with simpler needs.

C is being slowly superseded by C++ in many embedded applications, but it is peculiar that C is still largely used in mission and life-critical software. The most unsafe language is used for the most critical applications. Indeed, in these contexts, you can’t use C as you will, you are constrained into a limited subset that is designed to prevent programmers (sometimes even experienced ones) from shooting themselves in the feet. Nonetheless, those frameworks, although limiting the damage, can’t do much about memory safety and language naivety. The lack of proper encapsulation, strong type checking, a standard memory-safe container, or a string library makes the guidelines ineffective. Wheels get reinvented everywhere, each time increasing the chance of inserting a bug. Each time a missing check may let an invalid pointer slip through and even if an invalid pointer is caught deep down in the code, not much can be done about it but returning an error.

The more you push and strip the C language to avoid dangerous behavior, the harder and more expensive it becomes to write useful code. Consider accessing an array – a[i], in order to turn it into a memory-safe construct, you should add a check with the array size, requiring propagating the array size along with the pointer to its first element and accessing it only via an accessor function.

This boilerplate code is generally avoided in any other programming language (even C++ if you stick with standard library constructs and avoid the operator[] overload).

What does it mean for C programmers? Well, considering that Cobol programmers do still find jobs today, it is not the time for despair. But for sure it is time to start having a look in the programming language neighborhood, considering acquiring (or translating) skills in other languages, even if you won’t end up using that language, you will have gained new insights into how to write code. Rust and OCaml are for sure good points where to start, but also Ada could make a comeback.

C-only companies can’t turn on a dime dumping company assets and rewriting everything into a safer language. Recognizing this, CISA asks for a roadmap – a plan for increasing the memory safety of their products. What kind of approach can be devised?

My idea is that the product should be analyzed and partitioned into units that can be migrated one at a time. Starting from the most function-critical, and then all the rest software can be improved progressively. Static analysis tools may also offer this kind of insight, alongside usual diagnostics, the tool can pinpoint dangerous areas, where pointers or dynamic memory are overly exercised. AI can be used to identify boundaries and prepare stubs to glue C to another language.

For sure there are no easy times ahead. This transition will cost money. C and C++ jobs will shrink, while there will be new opportunities opening up for other languages. From consumers’ and users’ perspective, this is a turning point, software companies won’t be able to provide software as-is without warranties of any type. The cost of malfunctions (at least those related to memory safety) won’t be on customers and users anymore.

https://www.linkedin.com/feed/update/urn:li:activity:7260671529288417283
  1. Of the current top 10 programming languages in the TIOBE Index, C is the only one without object oriented programming support, one of the two not supporting lambda functions, and the only one not supporting a module/namespace concept. ↩︎

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.