Hacker News new | past | comments | ask | show | jobs | submit login

With all due respect, this is coming from a Win32 API C programmer who happens to save the code in files with .cpp extension. In other words, not familiar with modern C++.



Irrelevant. All the old, problematic approaches are still valid code, and hence from a security perspective they are vulnerabilities. Whether or not you, personally, trigger those vulnerabilities or not doesn't matter: the stack is vulnerable.

Note that you might choose to forbid anything that doesn't count as "modern C++", e.g. by enforced linting. Equivalently, you could instead have your compiler reject such programs (perhaps deciding to rip out various features and modules from the compiler, to avoid them being used). Either way, you're no longer writing C++: you're writing some other language (say, "C+++"), which is a sub-set of C++. In which case, you've done what the author suggested: deprecating C/C++ in favour of something safer!


> All the old, problematic approaches are still valid code, and hence from a security perspective they are vulnerabilities.

So, you would mandate using Rust without "unsafe", then? Good luck with that.


Perfect is the enemy of good. If you can avoid "unsafe", then yes: forbid it. If you can't, then permit it for only those modules which need it; and have them expose a safer API, for use by the rest of the safe-subset-of-Rust system.


This argument is indistinguishable from what you are trying to rebut.


What's wrong with .cpp extension?


The implication is that he's mostly writing C despite the file extension suggesting they contain C++.

C++ changed a lot over time, and the way modern code is supposed to be written is very distinct from "C with classes", but you still can do that if you want.


>the way modern code is supposed to be written

Many experts disagree with the way modern C++ evolves.

To say that modern code is supposed to use all the C++11-forward features or else it's obsolete is a massive bias on your part.


C with classes originally meant non oo c++. It was a common crticism from a time when not being oo was considered a defect rather than a design decision on which paradigm fit your problem space. It would be like a haskell zealot saying someone's clojure was "java with lambdas" to imply it was imperative. Implying imperative code was always inferior.

All that said, some parts of moder c++ like move semantics do really cut down on defects. People who go out of their way to use *all* of the new toys create codebases that make my teeth itch.


The "classes" part explicitly means OO.

It meant not using stuff like templates, operator overloading, RTTI, exceptions, STL.


Wut? Makes no sense to me.


Here's an example of C++ code written intentionally with all the latest C++ features:

https://gist.github.com/caiorss/c7db87df674326793431a14006aa...

It looks pretty much nothing like a C program doing the same job.

A lot of those features were made to make C++ a safer language to use. Eg, with a construction like:

    for(const auto& it : ast){
You can't accidentally walk past the end of the array by going one item too far. But C++ still allows you to write code the way you'd do it in C.


Sure, but it’s not enough.

You can forget the virtual destructor. Maybe the language is excused because it’s only a leak.

You could mess up the what() functions. (It’s not locally obvious that it’s correct in this code.) std::exception is fundamentally dangerous. Rust can get away with safely returning references like that because the lifetime is part of the function’s signature. C++, even modern C++, can’t.

Even the iterative example is only a bit safe. You can’t walk off the end by going one too far, but you can certainly mess up by invalidating the iterator in the loop body.


> You can't accidentally walk past the end of the array by going one item too far.

AFAIK, that's with a caveat of "unless you modified the array length within the loop" (looking at the gist, "ast" is a deque, so you can pop items from either end); IIRC, that C++ construct evaluates the begin and end only once at the start, instead of every iteration (unlike what you might do with "classic" C++ evaluating "it != ast.end()" every time), so it wouldn't notice the change. This is particularly annoying since C++ developers can be tempted to optimize a classic "for (auto it = ast.begin(); it != ast.end(); ++it)" loop into either the new-style "for (auto it : ast)" or the old-style optimized "auto end = ast.end(); for (auto it = ast.begin(); it != end; ++it)" loop, even though that would break the code if "ast.end()" ever changes within the loop.

(Since the initial discussion is actually about C and C++ versus Rust: in Rust, you wouldn't be able to modify the array within the loop, since the iterator is borrowing it, so this issue would be caught by the compiler.)


Thanks for the example!

Checks linked resources

      while(!ss.eof()){
        ss >> token;
Can cause an endless loop (with finite input stream; for example in case of a read error).

    p >> x;
    if(!p.fail() && p.eof()){
This way of error checking is correct for C++ but not nice (it or part of it can be forgotten with no warning--see below for an instance of it :P).

    struct stack_empty_error: public std::exception{
      const char\* what() const throw(){
Missing "override" annotation here. Can easily fuck it up since overloads are allowed.

        return " ==> Error: stack empty." ;
      }
    };



    auto x = _stack.back();
    _stack.pop_back();
    return x;
Correct in C++ but incredibly weird--typical for lowlevel languages that are far away from the user.

Also, when I press Ctrl-D, I get an endless loop printing "EXPR+> stack". Typical C++ program...


Why some functions are declared like:

    void foo()  { .. }
And others

    auto foo() -> void { .. }


Fashion.

The second syntax was introduced for lambdas and decltype() usage for return types that depend on the parameters (due to look up rules), and some C++ subcultures now use it everywhere.


>...And others

> auto main() -> int {

Absolutely no reason to masquerade main() in such a fashion!

It's a rule of least surprise, be it for user or fellow developer.


>...Here's an example of C++ code written intentionally with all the latest C++ features.

Does it really need to include <string.h>?


That's quite readable and actually makes me wanna try C++20 or whatever it is.


the gist is mostly c++11, all I can say is that c++20 is much better.

with constexpr etc, and std::move, and unique_ptr in use, many memory safety issues can be contained.

adding cppfront on top can make modern c++ even more memory safe.


Why are spaces randomly omitted for language constructs like if and for, and reference type &s left aligned?!


What's wrong with left aligned & and *? I prefer it because for me it makes more sense; it is not a <type>, it is a <type> reference (or pointer). This involves different semantics than just a <type>, so it makes sense to me for the extra information to be with the type.


Randomly? This author does it consistently. Some people prefer with spaces, some prefer without, most people follow the coding standards for the company / project they're working on.


In other words, you are not aware of anything wrong with this code.


They’re claiming the CTO of Azure doesn’t know enough about modern C++ to make the statement that we’re discussing.

Bold claim.


I find it hard to imagine the CTO of Azure has done enough C++ programming in the last few years to be fluent in C++20. Maybe as a hobby I suppose; it doesn't match my understanding of what a CTO of a big organisation does otherwise.


He doesn’t need to be fluent in every language to set technical direction as a CTO. You don’t question a general’s war strategy simply because they aren’t accurate with a rifle.


Absolutely, but that's not what this subthread is about. It started with zerr saying:

> With all due respect, this is coming from a Win32 API C programmer who happens to save the code in files with .cpp extension. In other words, not familiar with modern C++.

Edit: Ah, you said "know enough about modern C++", so yes, I agree and was arguing in the wrong bit of the thread.


If you're commanding officer orders a bayonet charge in the late 19th century it is safe to say they don't understand the change rifles have brought to the fight. Reference Picket's charge.


I was saying a commanders accuracy with a rifle isn’t relevant to their ability to decide tactics or strategy.

Nothing you’ve said contradicts what I said.


But the commander hasn't tried a machine gun and thinks that a bayonet charge will still work like it did before.


Don't you have that the wrong way round? In this tweet, Russinovich is arguing for the newer thing, not the older thing. The comparison would be the commander saying use a machine gun and consider bayonets obsolete, and the commenters who haven't used a machine gun are saying "he hasn't enough experience with modern bayonetting to say that, modern bayonettes wielded by sufficiently competent bayonetters are as good as any machine gun".

And then other critics saying "Russinovich hasn't demonstrated skill with a machine gun so how can he say bayonettes are obsolete?"


Or, the commander thinks that in an age of drones and cruise missles, bayonet charges don't make sense even if the bayonet is now attached to a machine gun.


And then the commander goes all in on that strategy, enemies knock out communication networks / find a drone counter measure, and now enemies have a decided advantages because they kept bayonets on their machine guns.


Aren't soldiers typically issued submachine guns? (That's what SMG is short for, isn't it?)

I think they might have been going for the ludicrous image of sticking a bayonette onto the front of a fixed gun emplacement.


It’s relevant. It’s harder to accept and follow a leader that can’t aim and shoot.


>He doesn’t need to be fluent in every language to set technical direction as a CTO.

No, but he does need to "know enough about modern C++ to make the statement that we’re discussing".


>You don’t question a general’s war strategy simply because they aren’t accurate with a rifle.

Thing is in this case their advice regards the rifle.


Right. So the general says we should use a different weapon. That’s fine. It’s also fine to question if that strategy makes sense.

It is nonsensical to say “the general can’t hit a moving target with the old rifle, so he should say nothing at all about weapons”. Which is what the person I replied to said.


The point the person you replied to was making was that him being CTO didn't add much credibility to his claim as you seem to assume by bringing it up, not that it necessarily removed credibility.


You should if the general came up during the flintlock era and now everybody is using machine guns. Plenty of people in World War 1 would have benefited anyways.

I could throw a bunch of examples further. For instance how the changes made to rifles because of what Generals thought their engagement ranges would be hampered the western forces who had to fight in Afghanistan.

You should also be skeptical of a General who suggests we go all in on Drone Warfare and not worry about rifles at all.

TLDR, person in a strategic role is rarely the best to assess tactical tools, and will often attribute strategic failures on their tactical tools.


No, but a good CTO would have people they trust telling them how it’s working. At Microsoft’s scale they could have an entire team auditing internal project stats looking at error rates, adoption of newer features, etc. - they spend more on toilet paper than that would cost!


All kinds of CTOs are not very technical in many ways.

They usually have not been in the trenches for a good while at least (could even be like 20+ years since they've done any development), and they take the ultimate decisions for their whole company for all kinds of languages and environments they have had no experience with... (like a CTO that used to do C back 20 years ago, now having a say in the use of Rust or Node).


C is not C++. While they strive for compatibility, I'm pretty sure there are cases where code compiled under a standards conforming C compiler will act differently under a standards conforming C++ compiler. Most C/C++ developers would compile a .cpp file with a C++ compiler if no other information was available.


Speaking of which, why do .cc and .cpp exist to refer to C++ source files? Two compiler vendors that couldn't agree?


You forgot .C (yes, uppercase C means C++, lowercase c means C), .c++ (the best one IMO), and .cxx (when your filesystem doesn't accept crosses, you tip them over). See https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Invoking-G_002... for the full list.


It's worse. Others include .cxx (fairly common) and .C (thankfully rare).


This may be a habit picked up by people writing more-modern-than-C89 C code that also has to be compiled by MSVC. Since MSVC is foremost a C++ compiler it was stuck in C89 for a very long time (I think it's better now, but old habits probably die hard).


Modern C++ is a scam.


They have played us for absolute fools


Can you please elaborate?


It's a meme template. The gp post didn't spend time to actually complete it, which is disappointing because it could be very funny.


Neither did you, so now we know a partial joke which could be funny but no one cared to elaborate.


You got me. I actually was thinking about what could go in it, but this is one template that actually takes work to do, so of course I didn't actually finish it.


I was being sarcastic. I find the assertion that modern C++ is a scam hilarious. It doesn't make any sense. Who benefits from this scam? Who are the victims?

The sentence is indeed from a meme template[1], but I thought that my comment would stand on its own.

https://knowyourmeme.com/memes/stop-doing-math


Thanks for elaborating. I've been hearing all sorts of criticisms of C++ ever since the 1990's (!!!) but I've been out of the loop for a little while and maybe need some catching up.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: