Why C and C++ Cannot Be Memory Safe

by Dipl. Ing. Frank Gerlach (frankgerlach.tai@gmx.de)

There are systematic reasons, why the current C and C++ standards cannot allow for guaranteed memory safety. The root cause are their type systems and established usage patterns. Memory Safety is a powerful concept, as it greatly limits the damage from programming errors, including the opportunities for cybernetic subversion.

1. Lack of Distinction Between Thread-Local and Thread-Global Variables

Both C and C++ have no concept of "data only reachable by local thread" and "data reachable by many threads". This creates dangerous race conditions, which easily destroy the integrity of heap memory. Also, reference-counted smart pointers can be implemented much more efficiently, if thread-locality is known.

Example of dangerous C++ thread-global variable:

//a global variable
::std::string globString;

//thread A
void* threadA(void* arg)
   return NULL;

//thread B
void* threadB(void* arg)
   return NULL;

In the the Sappeur language, the compiler will force the software engineer to use a "multithreaded" global variable, thereby automatically protecting all global methods by a mutex.

2. No Automatic Abolishing of Raw Pointers

Raw pointers are a rich source of exploitable memory errors and should be abolished in memory safe program text. They should be replaced by reference-counting Smart pointers or by a Mark-and-Sweep Memory Garbage Collection system. C++ Compilers should be able to report their use as errors.

The C language would have to be extended in order to make all pointers Smart Pointers. Many often-used patterns of the C language use raw pointers into raw arrays and are hard to conceive without raw pointers.

Point 2 is probably "too hard to swallow" for most seasoned users of C, which means C is unlikely to become memory-safe.

3. No Automatic Abolishing of Raw Arrays And Unsafe Vector Usage

Raw arrays and unsafe vector operations like ::std::vector::operator[]() are also a rich source of memory errors. Compilers should be able to report their use as errors.

4. No Automatic Abolishing of Crazy Casting

C and C++ allow for crazy type-unsafe casting of pointers like the following example:

int x;

RadarTrace* radarPtr = (RadarTrace*)x;

This is also a potential source of memory errors and compilers should have the option to report them as an error.

5. No Standard Way of Stopping a Stack Overflow

Obviously, a Stack Overflow must be stopped before it destroys unrelated memory. Currently there exists no standard way to do this in C and in C++. "Stopping" could mean either stopping the current thread or stopping the entire program, thereby creating an easy-to-debug core file. This aspect is important, but can probably be solved wholly on the compiler and code generation side, requiring no change of source code for most programs.

6. No Pointers To Stack

In C and C++, raw pointers can be obtained pointing to a stack variable, which might exist longer than the stack variable. Accessing these pointers are an obvious safety risk, with unlimited damage possible.

7. Use of this Pointer in the Destructor

In C++, the "this" pointer can be stored into another data structure, even though the pointer will be invalid in short order. This must be abolished in a memory safe language.

Formelles, Kontakt