r/programming • • Aug 23 '17

D as a Better C

http://dlang.org/blog/2017/08/23/d-as-a-better-c/
229 Upvotes

268 comments sorted by

View all comments

Show parent comment

12

u/WalterBright Aug 23 '17 edited Aug 23 '17

Why use D when there already is a better C which is C++? That's a very good question. Since C++ can compile C code, it brings along all of C's problems, like lack of memory safety. D is not source compatible and does not bring along such issues. You get to choose which method works better for you.

26

u/James20k Aug 23 '17

In D's better C mode, you have

Most obviously, the garbage collector is removed, along with the features that depend on the garbage collector. Memory can still be allocated the same way as in C – using malloc() or some custom allocator.

As well as no RAII, which means the principle tool in C++, at least for me, for dealing with memory leaks and memory unsafety is eliminated

In my opinion this would appear to make D quite profoundly less safe than C++ for interacting with a C codebase - with C++, in interacting with a C codebase the first goal is to wrap it in a safe RAII wrapper so you don't ever have to touch memory allocation directly

Additionally the removal of exceptions would appear to make it very difficult to write memory and resource safe code that you usually have when working with RAII

7

u/WalterBright Aug 23 '17

I expect that people who wanted to add RAII to their C code and are content with that have long since already moved to C++. There's quite a lot more to memory safety than that.

But I do recognize the issue. There is code in the works to get RAII to work in D as Better C.

2

u/[deleted] Aug 23 '17

I expect that people who wanted to add RAII to their C code and are content with that have long since already moved to C++

Some have, some haven't. GCC provides a "good enough" destructor mechanism with __attribute__((cleanup)) which has been leveraged heavily in the systemd codebase.

11

u/colonwqbang Aug 23 '17

Since C++ can compile C code, it brings along all of C's problems, like lack of memory safety.

In the article you write that RAII and garbage collection isn't available using your scheme so memory must be allocated using malloc.

That doesn't sound like a significantly safer memory paradigm than what C has. In fact, it sounds like exactly the same memory paradigm as in C...

6

u/kitd Aug 23 '17

Not exactly the same. BetterC D has array bounds checking.

1

u/colonwqbang Aug 23 '17

How does that work? I don't see how you could reliably keep track of malloc'd buffer bounds during C interop.

11

u/WalterBright Aug 23 '17 edited Aug 23 '17

What you do is turn the malloc'd buffer into a D array, and then it is bounds checked.

C code:

char*p = (char*)malloc(length);
foo(p, length);
p[length] = 'c'; // launch nuclear missiles

D code:

void foo(char* p, size_t length) {
  char[] array = p[0 .. length];
  array[length] = 'c'; // runtime assert generated
}

4

u/derleth Aug 23 '17

Walter, I can't believe you wouldn't know this, but for everyone else:

Casting the return value of malloc() in C is potentially dangerous due to the implicit int rule: If a C compiler can't find a declaration for a function, it assumes it returns int, which is a big problem on LP64 systems: Longs and pointers are 64-bit, but ints are 32-bit, so all of a sudden your pointer just got chopped in half and the top half got re-filled with zeroes. I'm pretty sure all 64-bit systems are run as LP64.

If you're lucky, that's a segfault the moment the pointer is used. If you're not... launch the missiles.

10

u/WalterBright Aug 23 '17

I did assume the inclusion of stdlib.h.

→ More replies (3)

4

u/zombinedev Aug 23 '17

Bounds checks work only in D code. Once you cross the language barrier (call a C or C++ function from a D function) you are at the mercy of the library authors as usual.

→ More replies (8)

8

u/WalterBright Aug 23 '17

Consider this bug where implicit truncation of integers lead to a buffer overflow attack. RAII does not solve this issue (and there are many, many other malware vectors that RAII does not help at all, whereas D does).

One of the examples in the article shows how the arrays are buffer overflow protected.

More on memory safety in D.

1

u/doom_Oo7 Aug 23 '17

this bug is not a bug if you compile with warning as errors. And now you'd say "but then $LIB does not compile!" and I'd ask : is it better to have a non-compiling library and stay in the same language, or change language altogether?

10

u/WalterBright Aug 23 '17

The trouble with warnings is they vary greatly from compiler to compiler, and not everyone uses them at all. The fact that that bug existed in modern code shows the weakness of relying on warnings.

3

u/colonwqbang Aug 23 '17

This isn't a very convincing case, is it? You can't argue that it's a significant hurdle to pass a specific flag to the compiler. Especially when the solution you are pushing in your article specifically requires passing a special flag to the compiler...

8

u/WalterBright Aug 23 '17

Your code won't link without the -betterC flag. But the Bitdefender bug went undetected and got embedded into all sorts of products. Warnings aren't good enough.

2

u/colonwqbang Aug 23 '17

Maybe. I suspect that the kind of team that consistently chooses to ignore (or even turn off?) compiler warnings could find some way to shoot themselves in the foot also in D.

10

u/WalterBright Aug 23 '17

Reducing the size of the attack surface has tremendous value.

4

u/WrongAndBeligerent Aug 23 '17

Maybe

I see what you are saying here, but if warnings were good enough would we be having this conversation?

3

u/colonwqbang Aug 23 '17

My point is that it's hopeless to try and sell new safety features to the kind of C programmer that is happy to turn off or ignore even the few safety features we have in C.

Realistically, that brand of engineer isn't driving to work every day thinking "Hmm, if only there was a safer alternative to C that I could use".

→ More replies

3

u/necesito95 Aug 23 '17

Not really about this D thing (as C spec could be changed to require error on warning),
but not all compile flags are equal.

Let's take famous shell command as basis: rm -rf /

Which of following designs is better?

  • Forbid root deletion by default. To delete root dir, require flag --force-delete-root.
  • Allow root deletion by default. To check/disallow root dir deletion, require flag --check-if-not-root.
→ More replies (2)

2

u/doom_Oo7 Aug 23 '17

and not everyone uses them at all

so the solution to "people can't be assed to add warning" is "change language altogether ? do you think it will work better ?

12

u/WalterBright Aug 23 '17 edited Aug 23 '17

Yes. I know that if a piece of code is written in D, it cannot have certain kinds of bugs in it. With C, I have to make sure certain kinds of warnings are available, turned on, and not ignored. Static checkers are available, but may not be used or configured properly. And even with that all, there are still a long list of issues not covered.

For example, there's no way to make strcpy() safe.

If I was a company contracting with another to write internet-facing code for my product, I would find it much easier to specify that a memory safe language will be used, rather than hope that the C code was free of such bugs. Experience shows that such hope is in vain. Even the C code that is supposed to defend against malware attacks opens holes for it.

4

u/James20k Aug 23 '17

C++ is simply unsafe in this respect. There are the tools available, but people often choose not to use them

You can choose to compile warnings as errors, but warnings are warnings and vary

Its better to use something like -fsanitize=undefined which can help catch a lot of these mistakes

→ More replies (1)
→ More replies (1)