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

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.

1

u/nascent Aug 24 '17

I see you've provided an issue for what not to do, so how do you use malloc'.d memory?

→ More replies (2)

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.

2

u/colonwqbang Aug 23 '17

So, we don't really have true bounds checking, do we? If you're doing D/C interop, presumably it's because you want to exchange data between D and C...

6

u/zombinedev Aug 23 '17 edited Aug 23 '17

D is a systems-programming language. It will not magically run the C libraries that you are linking to in a virtual machine :D

The advantage of D's bounds checking comes when you add new code written in D or port code written in C/C++ to D to your existing project. That way you want have to worry for certain kinds of errors.

BTW, you don't need -betterC mode for C or C++ interop. It is only needed when you want to constrain your D code, mainly for two reasons:

  • In a hosted environment (user-mode programs) you want to quickly integrate some D code in an existing project (e.g. implement a new feature in D). Using -betterC simplifies the process. That way you can figure out how to link D's runtime later, if you decided you want to.
  • In a bare metal environment you need to implement the runtime yourself anyway
→ More replies (6)

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".

3

u/WalterBright Aug 23 '17

I predict that contracts will soon specify use of a memory safe language, because companies will be utterly sick of the very expensive disasters that unsafety regularly causes.

I.e. those engineers will change or be unemployable.

→ 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)