Live data from Hacker News

My Most Important C++ Aha Moments (2006)

artima.com

71–80 of 84 posts

Re: My Most Important C++ Aha Moments (2006)

#71

Earlier quoted context omitted.

> Yes, it does. Where is this modern C++ culture that has resulted in large-scale codebases free of memory safety vulnerabilities? I've never seen even one , much less a "widespread culture". > The majority of C++ programmers make use of: None of this, empirically, results in safe code. > Most of the unsafe C++ code is written by the "C with C++" sub-community that are mostly C refugees forced to use a C++ compiler.…

> Robert O'Callahan and I have elaborated why in other posts. One point of note is that O'Callahan's "Vapourware" post points out a problem that's solvable, it isn't some big blocker the way he claims it is. Your comment 162 days ago describes the real problem, or at least one of them. Edit, because fuck: > Where is this modern C++ culture that has resulted in large-scale codebases free of memory safety vulnerabiliti…

> One point of note is that O'Callahan's "Vapourware" post points out a problem that's solvable, it isn't some big blocker the way he claims it is.

No, it is a big blocker. In fact, it's the same as the problem I pointed out, just with global variables instead of shared ptr. Aliasable mutable data is the fundamental unsolvable problem; whether it arises through global variables or shared ptr is just a detail.

> The rest of your post shifts the question from "is there a culture of secure, maintainable, and understandable software" to "Is C++ software free of memory flaws." Are these concepts not distinct to you?

Software that has memory flaws that enable remote code execution is not secure.

Re: My Most Important C++ Aha Moments (2006)

#72

Earlier quoted context omitted.

> Robert O'Callahan and I have elaborated why in other posts. One point of note is that O'Callahan's "Vapourware" post points out a problem that's solvable, it isn't some big blocker the way he claims it is. Your comment 162 days ago describes the real problem, or at least one of them. Edit, because fuck: > Where is this modern C++ culture that has resulted in large-scale codebases free of memory safety vulnerabiliti…

> One point of note is that O'Callahan's "Vapourware" post points out a problem that's solvable, it isn't some big blocker the way he claims it is. No, it is a big blocker. In fact, it's the same as the problem I pointed out, just with global variables instead of shared ptr. Aliasable mutable data is the fundamental unsolvable problem; whether it arises through global variables or shared ptr is just a detail. > The r…

> No, it is a big blocker. In fact, it's the same as the problem I pointed out, just with global variables instead of shared ptr.

Imagine refactoring a program to not use globals but instead pass them up by const or mutable reference to where they're used. The checker can do the same imagining with an effect system.

> Software that has memory flaws that enable remote code execution is not secure.

Words have meaning.

Re: My Most Important C++ Aha Moments (2006)

#73

Earlier quoted context omitted.

Alternative view: if you must use C++, stick to nothing later than C++2003. Anyway, declaring a constructor " = delete" isn't the same thing as making it private. If it's private, the code in your class scope can still use it. If you can't trust your class private code to do things correctly, then you're screwed; go join IT and write backup shell scripts. So basically this "= delete" is just another ear growing out o…

The reason for testing and static typing is that you can't trust yourself to be perfect. I want to declare that I won't do things that don't make sense, so the tools will tell me if I do them unintentionally.

In 1998 C++, we can solve the problem of how to make a class non-copyable, even to code that is in its class scope.

We can create a dummy class which has a private copy constructor that is not implemented:

  class noncopyable {
  private:
    noncopyable(const noncopyable &);
  };
then simply make this a data member of a class that you don't wish to be copyable:

  class whatever {
  private:
    noncopyable nc;
  };
The default copy constructor generated by the C++ compiler performs a member-for-member copy, which involves copying nc. That is not possible, so in effect that copy constructor is defeated, not unlike by "= delete".

Alternatively use inheritance to mix this in as a trait:

  class whatever : private noncopyable {
    // ...
  };

Re: My Most Important C++ Aha Moments (2006)

#74
post #49

Earlier quoted context omitted.

Indeed that not only you have to follow, everyone else on the project has to follow, as well as every newcomer and every piece of third-party code that is brought in. "Avoid the parts you don't like" works best for one programmer working alone.

I had an instructor once that insisted on having a single exit point for all loops. "Never use break or continue or return from a loop." The argument was that understanding control flow is more complex when you don't have to deal with these things. However, those things exist in the language. You can't just pretend nobody is going to use them, because there might be very good reasons to use them, especially in an imp…

In the world outside of that instructor's classroom, there are coding conventions which forbid certain things, with excellent reasons for doing so.

Back when ISO C++ was still staffed by people with useful ideas, they invented various more specialized, safer casts that refuse to do "off topic" conversions. These replace the "(type) expr" C casting notation.

A C++ coding convention document can cheerfully forbid C style casts; there isn't any reason to use them.

Re: My Most Important C++ Aha Moments (2006)

#75

Earlier quoted context omitted.

> One point of note is that O'Callahan's "Vapourware" post points out a problem that's solvable, it isn't some big blocker the way he claims it is. No, it is a big blocker. In fact, it's the same as the problem I pointed out, just with global variables instead of shared ptr. Aliasable mutable data is the fundamental unsolvable problem; whether it arises through global variables or shared ptr is just a detail. > The r…

> No, it is a big blocker. In fact, it's the same as the problem I pointed out, just with global variables instead of shared ptr. Imagine refactoring a program to not use globals but instead pass them up by const or mutable reference to where they're used. The checker can do the same imagining with an effect system. > Software that has memory flaws that enable remote code execution is not secure. Words have meaning.

> Imagine refactoring a program to not use globals but instead pass them up by const or mutable reference to where they're used. The checker can do the same imagining with an effect system.

Not at all. This requires higher order control flow analysis, which is pretty much guaranteed to fall down in all sorts of cases.

Re: My Most Important C++ Aha Moments (2006)

#76

Earlier quoted context omitted.

> No, it is a big blocker. In fact, it's the same as the problem I pointed out, just with global variables instead of shared ptr. Imagine refactoring a program to not use globals but instead pass them up by const or mutable reference to where they're used. The checker can do the same imagining with an effect system. > Software that has memory flaws that enable remote code execution is not secure. Words have meaning.

> Imagine refactoring a program to not use globals but instead pass them up by const or mutable reference to where they're used. The checker can do the same imagining with an effect system. Not at all. This requires higher order control flow analysis, which is pretty much guaranteed to fall down in all sorts of cases.

But you don't need the system to be precise or accept every correct program. Heck, you'd get pretty far with a simple conservative yes/no on whether a function might touch any globals. At least at that point you could copy-construct from a global. You could skip adding any complex mechanisms and just say, hey, every function instantiation/global variable combination is going to get a plain mutates/reads/no, which translates to how things would be if the mutable/const references was passed up from main, and if that ain't flexible enough for you, have your closure/object capture a reference to the global and we'll track it that way. [1] Of course that could get replaced with a specific annotation mechanism where we don't really put a reference in the object. But regardless, what this does is handle the problem of global variables for the set of global-using programs which you could still write, without having to think too much, if there were no global variables in the language at all.

[1] Edit: A mechanism for annotating that a class or method does not get implicitly passed globals would be very useful for things like std::function::operator() so that std::function objects are forced to access globals by capturing them, because totally unrelated uses of a std::function could stomp over the same type instantiation for this ultra-dumb analysis.

Edit: Here's the tl;dr version. One solution to the global variables problem is for the CppCoreGuidelines to say, "Don't use globals." Another is for them to say, "Don't use globals, but for the 90%-case we won't be dicks about it, we won't blindly pretend that every function could use globals when they obviously don't."

Re: My Most Important C++ Aha Moments (2006)

#77

Earlier quoted context omitted.

> Imagine refactoring a program to not use globals but instead pass them up by const or mutable reference to where they're used. The checker can do the same imagining with an effect system. Not at all. This requires higher order control flow analysis, which is pretty much guaranteed to fall down in all sorts of cases.

But you don't need the system to be precise or accept every correct program. Heck, you'd get pretty far with a simple conservative yes/no on whether a function might touch any globals. At least at that point you could copy-construct from a global. You could skip adding any complex mechanisms and just say, hey, every function instantiation/global variable combination is going to get a plain mutates/reads/no, which tra…

> Heck, you'd get pretty far with a simple conservative yes/no on whether a function might touch any globals.

No, you wouldn't. Try writing such an analysis. Either I will be able to break your analysis or it will return "yes, this might mutate a global" for so much of any reasonably sized program that the analysis will be useless.

This is basic, basic stuff to anyone who is in the sound static analysis field.

Re: My Most Important C++ Aha Moments (2006)

#78

Earlier quoted context omitted.

But you don't need the system to be precise or accept every correct program. Heck, you'd get pretty far with a simple conservative yes/no on whether a function might touch any globals. At least at that point you could copy-construct from a global. You could skip adding any complex mechanisms and just say, hey, every function instantiation/global variable combination is going to get a plain mutates/reads/no, which tra…

> Heck, you'd get pretty far with a simple conservative yes/no on whether a function might touch any globals. No, you wouldn't. Try writing such an analysis. Either I will be able to break your analysis or it will return "yes, this might mutate a global" for so much of any reasonably sized program that the analysis will be useless. This is basic, basic stuff to anyone who is in the sound static analysis field.

> Either I will be able to break your analysis or it will return "yes, this might mutate a global" for so much of any reasonably sized program that the analysis will be useless.

The point is, you can write functioning programs even with that -- you can copy construct out of a global, for example, but you obviously can't pass string literals to functions that touch stdout or errno. If you want to make a legitimate disagreement, argue against the more practical version where you treat different global variables as different things.

> This is basic, basic stuff to anyone who is in the sound static analysis field.

Do people in that field also nitpick pieces of rhetoric and deliberately ignore the main point?

I don't think any intelligent person in that field would argue that C++ programs can't be written or refactored in such a way so as to get rigid enough use of globals so as to pass a relatively conservative analysis. I mean, that would imply you couldn't get anything useful done in a language without globals.

Re: My Most Important C++ Aha Moments (2006)

#79

My most important C++ Aha moment was in 1995 when I wrote my first lines of Java and realized that it was possible to write OO code without having to fight the compiler every step of the way.

My Aha moment was in 2008 when I saw a java program consume 400+mb of RAM for a text editor. Then if you clicked on too many things, it crashed under its own weight (eclipse).

"But it has garbage collection" they said. "You dont have to worry about pesky memory managment, the language has an intelligent VM that handles it for you!".

Re: My Most Important C++ Aha Moments (2006)

#80

Earlier quoted context omitted.

qmail is supposed to be used with "softlimit" from daemontools. All decent tutorials mention that. Again, which C++ program has been even analyzed to that level?

Did it ever occur to you that if a C++ programmer of security mindset wanted to make something like postfix or qmail, they'd just pick a language that was garbage collected?

No, it did not occur to me. The reason is precisely that I have not seen this mindset among C++ programmers, at least in the open source world. Llvm is an exception.

What I do see is hubris. They are overconfident and pretend that one can use C++ like Haskell, i.e. one can safely go ahead and pile one abstraction onto another.

C programmers at least know the limitations of their language.

This is the just impression that I and many others get. I'm sure there are counterexamples.

Post reply on HN