← Back to context

Comment by pcwalton

10 years ago

Undefined behavior in the form of memory safety issues is a problem in day-to-day work.

UB and memory safety are a big issue exactly because they are not a problem in day to day work.

I literally can't remember the last time I had spent any significant time investigating one of these issues. In my experience when that a crash happen (usually in a unit test or the first time you start the app) because of these issues, the backtrace points you to the exact problem.

The pain start when the program and tests work correctly for all reasonable inputs and the underlying issue never manifests in during normal execution and can be potentially exploited by a malicious attacker with a carefully crafted input.

What I'm trying to say is that I don't want memory safety because it would improve my daily programming experience (in fact possibly the reverse would be true), but I want it because I want security.

  • > What I'm trying to say is that I don't want memory safety because it would improve my daily programming experience (in fact possibly the reverse would be true)

    I think you underestimate how much time is saved by not having to deal with these issues. Programming in C or C++ is frequently an exercise in writing the code, seeing a crash due to a memory safety problem, debugging it, and then repeating until you see anything resembling a working program. Writing in a memory-safe language lets you skip all that startup friction and go straight to "something resembling a working program".

    • I don't know, I don't think I spend even a couple of hours per month inside a debugger. I doubt my colleagues do either. Usually I write code for 1-2 weeks, then spend one day trying to get it to compile then one or two days debugging it, but most of my debugging sessions is trailing logs and trying to figure out what went wrong with in complex state machines (i.e. the business logic, not the language/infrastructure 'overhead').

      Also, many of the data structures I deal with are highly intrusive (as in an object belonging at the same time in multiple containers) and short of full GC I doubt it would be easy to guarantee MS.

      Then again, possibly I'm not representative of the typical C++ programmer.

But that's not what this study is about: everyone agrees that stomping wildly off the end of an array in C is not going to end well.

This is about far more subtle issues than that - issues where there is some disagreement about whether it's OK to do or not. And the GP is right - these are often not such a problem in practice, if only because these are the kinds of issues where experienced C programmers know that they're sailing close to the wind, and there's almost always an alternative construct that's on more solid ground.

  • Signed versus unsigned comparison, signed wrap-around, undefined division behaviour, undefined behaviour of some casts, and strict aliasing optimisations have all caused hard bugs that I've had to spend a lot of time fixing.

    I had to deal with some of these before I was a compiler writer, and I would end up just kind of kicking my code repeatedly until stuff worked again.

    Now that I'm a compiler writer, I know how to recognize what is happening, but I'm still not smart enough to avoid the bugs in general and I still spend time fixing bugs that result from these issues.

    So, I'm with pcwalton: it is a problem. Maybe I don't see it every day, but I see it probably at least once a month.

    • There are fewer issues that scare me more than undefined behavior that usually works. "Works" enough for programmers to add it, knowingly or unknowingly, even to defend it as "working in practice"... only to leave a needle in a haystack that they'll never find.