On Thursday, 3 December 2015 at 00:31:46 UTC, Andrei Alexandrescu wrote:
Nice. What I'd say is that at the end of the day there's documentation. -- Andrei

Just to provide a bit of perspective...

Although memory corruption may not seem so scary in short-lived programs where it can be trivially reproduced with the same input, it can be an absolute nightmare when it occurs in long-running server processes, for developers, sysadmins and end-users alike.

A long time ago, a network service I wrote started having severe memory corruption issues. It went from crashing about once a day to once every few hours, and every time it crashed it pissed off a dozen users or more. Great ire and vitriol[1] was expressed towards the service, and everything I tried only seemed to make the situation worse.

It took months of studying and playing with D GC internals (incl. unsucessful attempts to use the GC's own debugging code and additional debugging GC proxies - see Diamond), and finally after three nights of replay debugging a virtual machine which recorded a crash on my home PC, and trying to infer meaning from memory dumps of GC control structures, I've tracked down the bug. The final result was the addition of InvalidMemoryOperationError to Druntime.

So, this is why I am on a war campaign against anything that might result in memory corruption in D. Another recent example was the controversy over readln (yes, std.stdio.File.readln, one of the basic operations in any programming language) corrupting memory: sure, this patch will make D programs no longer crash and burn in weird ways, but it will also make readln slower! Think of the benchmarks! Thankfully a solution was found which was both safe and acceptably fast.

You said that "at the end of the day there's documentation". I would argue that at least in this case, it may not be enough. Consider, for example, a hypothetical user type "Pack", which takes a tuple/struct and automatically arranges the fields into a struct such that space is used optimally (e.g. all bools are clumped together into a bitfield, enums are only given as much bits as their .max needs, etc.). Pack only needs to know one property of each field: how many bits it really needs, and as such, it might elect to be agnostic of what a pointer is. If it uses std.bitmanip.bitfields as its backend, it will happily pack a pointer at its user's request, and the user will never see the pointer warning in Pack's documentation. And yes, although it's easy to point the finger at users and say "ha ha, it's your own fault, you did not RTFM", I think we should strive for better than that.

I was recently close to having a repeat of the memory corruption situation (with the same service, too) due to the struct alignment issue. Luckily there was only one week of strife before I narrowed down the bug. Memory corruption may only manifest in certain conditions (e.g. release mode, after updating/switching compilers), and rollback/bisect are not always viable or useful options. Even if the issue I filed had been fixed at the time, it would not have helped in that particular case, since, well, D is unsafe by default, and it is situations such as these that make me occasionally glance in Rust's direction.

[1]: http://dump.thecybershadow.net/41a97cdab29f9cd56340ce8a5163d6f8/rage.txt

Reply via email to