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

> When you want to use a language that gets compiled and runs at high speed, the best language to use is C. C++ is ok too, but please don’t make heavy use of templates. So is Java, if you compile it.

Back in the early days, this sentence was more like "When you want to use a language that gets compiled and runs at high speed, the best language to use is C.".

So we switched from a path where all major desktop environments (OS/2, Mac, Windows, UNIX) were adopting C++ to a surge in C programming, as FOSS adoption started to gain steam.

So here we are now, about 30 years later, trying to fix the security inconveniences caused by this manifesto.




> So we switched from a path where all major desktop environments ... were adopting C++ to a surge in C programming, as FOSS adoption started to gain steam.

So you say FLOSS is responsible that the late 90s/early 2000s C++ hype slowly died off?

> trying to fix the security inconveniences caused by this manifesto.

And you believe those projects chose C, solely because some random GNU document suggested they do?

If that document didn't exist they would have chosen what? C++98? Java? Ada?


In part yes.

Had GNU/Linux not taken off, in the alternative universe from Windows, BeOS, Mac OS, OS/2, commercial UNIX (remember Motif++ and CORBA?) would kept writing the software in C++, instead of caring about creating FOSS stuff in C.

GNOME vs KDE is a good example of that schism and language wars.


Having written software in the 90s: C++ was unusable for large-scale apps on commodity hardware. It was a neat toy. It had humongous compile times, and the runtime was suboptimal at best.

The choice was protracted language wankery with continuous (wrong) declarations of "Soon, the compiler will make it fast enough", or actually shipping software.

The balance started tipping in the early to mid-2000s. You could, if you were very careful, write decent-sized systems with good performance in C++ at that point, and the abstractions were starting to be worth it.

And I say that as somebody who enjoys C++, and has written code in it since the late 80s. Yes, on cfront. "Horses for course" always has been, and always will be, the major driver for language adoption. That particular horse wasn't ready in the 90s.


> And I say that as somebody who enjoys C++, and has written code in it since the late 80s

As have I, and I say you don't seem to know what you are talking about. I've been involved in writing very large Unix and Windows applications in the 1990s (starting in the late 80s), and have had no problems that you mention.


I remember CORBA. Oh, god, do I remember CORBA. I wish I could forget CORBA.


It is called gRPC nowadays.


All of those operating systems kernels were written in C (and ASM) not C++.


Where did I mentioned the kernel?

And no, that is not correct.

Mac OS was a mix of Object Pascal (originally created by Apple), Assembly and C++.

Windows (32 bit variants) and OS/2 userspace has always been a mix of C and C++.

BeOS userspace was C++.

Symbian was full C++, including the kernel by the way.


> Mac OS was a mix of Object Pascal (originally created by Apple), Assembly and C++.

That doesn't ring true at all.

Object Pascal was a rather short-lived project at Apple. It was only seriously used for the MacApp framework -- which was a separate product sold to application developers, not part of the core OS or development tools -- and was abandoned entirely during the PowerPC transition. Later versions of MacApp used C++.

The bits of source code I've seen for System 7 were primarily C and assembly, with some older code in (non-object) Pascal. I don't recall seeing any C++.


I checked through the source code for System 7.1 at https://www.macintoshrepository.org/1398-mac-os-7-1-source-c... . You look correct (A=assembly, H=header, C=c, P=pascal, R=resource)

    % find ~/Downloads/System\ 7.1\ Source/ -type f -print0 | xargs -0 -n 1 basename | cut -d. -f 2- | tr '[a-z]' '[A-Z]' | sort | uniq -c | sort -rn | head -20
      869 A
      308 H
      189 C
      162 P
       85 R
       69 MAKE
       31 M.A
       28 O
       11 RSRC
       11 AII
    ...


Would you say that the predominance of C++ rather than C in FLOSS would have a net positive result?


Yes, because while it isn't fullproof due to copy-paste compatibility with C89, at least it offers better tooling for safer coding, provided one doesn't code "C with C++ compiler".

Namely:

- proper string and vector types (most compilers allow to enable bounds checking anyway)

- stronger rules for type conversions

- reference types for parameters

- better tooling for immutable data structures

- memory allocation primitives instead of getting sizeof wrong to malloc()

- collection library instead of reinventing the wheel in each project

- RAII

- smart pointers

- templates instead of error prone macros

- namespacing (usefull in large scale projects with prefix tricks)


A large number of those came only usefully into existence in 1998, with C++98

string & vector types: STL, 1998 type conversion operators: 1998. mutable keyword: 1998. collection library: STL, 1998. smart pointers: STL, auto_ptr<> in C++98

I'd argue that without STL & C++98, C++ would've languished even longer. And with STL, it still took another 5 years for the compilers to be good enough.


> And with STL, it still took another 5 years for the compilers to be good enough.

This is under-stated, IMO. It wasn't really until 2004 or even later that we had high-quality support for C++98 in GCC. LLVM wasn't available, yet. Heaven help you if you wanted to develop in C++ on OSX, since Apple's packaging of GCC was a total disaster. Step zero for developing C++ on OSX was "install GCC from FSF sources" for many years.

Even MSVC support was lagging. It wasn't until the Microsoft tools leadership got involved with C++11 that MSVC took standard support seriously. They were already prioritizing .NET in that timeframe.

Meanwhile, the big open-source desktop C++ libraries (Qt and WxWindows) still don't fully take advantage of the types and features in the standard library in 2021.


> Heaven help you if you wanted to develop in C++ on OS X, since Apple's packaging of GCC was a total disaster.

If you were developing Mac programs in C++ back then, you were probably using Metrowerks CodeWarrior.


> Meanwhile, the big open-source desktop C++ libraries (Qt and WxWindows) still don't fully take advantage of the types and features in the standard library in 2021.

Of course not. C++ and libraries don't go along nicely. STL is not really useful for cross boundary interop due the fact that C++ ABI is not stable.

Shipping libraries that leak STL types all over the place will only give you headache.


I also have a copy of P. J. Plauger's Draft Standard C++ Library.


Good news! GNOME and KDE both have efforts to add more Rust: https://wiki.gnome.org/Projects/Rust https://community.kde.org/Rust


The average C++ code base has as many segfaults than the average C code base.

Windows has more exploits than Linux. But you know all that, so I wonder why you keep making these statements, which are then upvoted by the "memory-safe" crowd.


I’m glad this doesn’t go unnoticed, and share the observation. There seem to be quite some effort going into creating illusions of truth about C. Just a personal observation.



If you want to play that game, https://www.cvedetails.com/product/32238/Microsoft-Windows-1... shows Windows, indeed, having more CVEs, in spite of, AFAIK, not using C (substantially, at least). Of course, the real problem is that CVE counts may or may not mean anything when comparing systems with wildly different development models (FOSS/proprietary) used mostly in different areas (desktop / everything else).


> The average C++ code base has as many segfaults than the average C code base.

any source for that ? I find segfaults utterly rare in C++ >= 11


You were using C++ >= 11 in 90s/00s?


I can't speak for the parent, but I've been using RAII and smart pointers in the 00s and it provided a lot of the benefits that got standardised with C++11.


None of that was a thing in 90s and early 00s.


RAII and smart pointers definitely were a thing in the 90s. I wrote lots of COM code using these techniques. According to wikipedia, RAII was invented in 1984-89.


The average C++ codebase isn't from the 90s. On all the recent c++ polls the average language revision used is between c++14 and 17.

Besides I'm pretty confident that there are more new c++ projects created daily in 2021 than monthly at the peak of the 90s c++ craze - just on GitHub, 6/7% of C++ repos means a few million recent C++ repos.


I've worked on several code bases that nominally are C++11 or 14. However they still contain a lot of code written by people still coding like it's the 90s.


What does it have to do with what we are discussing?


we are discussing the sentence "The average C++ code base has as many segfaults than the average C code base."

__s and you said "You were using C++ >= 11 in 90s/00s?" to which I answered that this was not the point, because the average C++ code base isn't from the 90s/00s.


> On all the recent c++ polls the average language revision used is between c++14 and 17.

Polls of hobbyist coders, or software houses? I would be surprised if most software houses migrated to C++17 yet. Tensorflow is stuck on C++03 I think.


TF is at least C++11 from the first header I opened in the repo: https://github.com/tensorflow/tensorflow/blob/master/tensorf...

I'm referring to e.g. the Jetbrains and cppcon polls.

https://blog.jetbrains.com/clion/2020/06/dev-eco-cpp-2020/

https://youtu.be/JYzDpXI-vWI?t=137


Last time I used it there was faff around having to define __GLIBCXX_USE_CXX11_ABI=0


it does not mean that you're not using C++11. This macro is just a compatibility flag for your code to work on old linux distros that provide a C++11 compiler but did not want to rebuild their whole archive. It mainly means that std::string is implemented with copy-on-write instead of small buffer optimization.


Sure it was, Borland and Microsoft compilers already had smart pointers for COM libraries.

Besides even on MS-DOS with frameworks like Turbo Vision, RAII was a common pattern.


auto_ptr (precursor to unique_ptr) was first proposed for standardisation in 1994 [0], and there was probably non standard versions of it before 94.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1994/N055...


You ever used auto_ptr?

In 1992, I was working on the Taligent project, probably the first major C++ operating system. (It failed.) I remember when the ARM came out---none of the compilers we had available could really do templates. Or namespaces.


A part of Taligent lives on with ROOT, which was very annoying.


Oh no... ROOT. It's a testament to the pure grit and gumption or thousands of poor undergraduates that particle physics can advance, with this. Eons ago, I tried several times to help my then-girlfriend (you know how it goes 'hey you have some kind of eng diploma'? Yes sw engineering... - Hu so you know C++? - nobody 'knows' C++ but I can manage 'so here what I'm trying to do, here are 3 other examples, please for the love of Wotan help') and I was baffled on how to do anything with it. I mean the core thing seems powerful enough, but trying to go out of the beaten path (research, right ?) was yugely frustrating... And I'd worked on 2 physics codebases or variable quality before. I didn't appear as competent as I'd hoped and spent so much time helping, reading docs and code without understanding much of the design. This is the codebase that started my deep defiance for OOP and especially OOP-as-a-mirror-of-the-real-world and inheritance-for-code-economy...


ok then, nobody was using auto_ptr in the 90s.


Oh boy, OWL, MFC and VCL were used in the 90s, with their ComPtr smart pointer for COM/ActiveX/OLE 2.0.


I worked with C++ & MFC in mid-late 1990s, smart pointers weren't an option. Maybe if you do something against MS oddball APIs, but not in general programming, not even for mainstream MFC uses. And what was there was entirely non-idiosyncartic, it's like claiming C++ had garbage collection in 1990s because you could bolt on Boehm's.


> So here we are now, about 30 years later, trying to fix the security inconveniences caused by this manifesto.

That sounds backwards to me. It wasn't a "manifesto" that caused that "surge", it was the actual software being written.

Free software beat the world. Free (system) software is overwhelmingly written in C. At least part of an argument like this needs to nod to the fact that free software written in C beat the world because... C was a better choice? Certainly it was in the 90's.


I've spent 10 years writing security critical C code. There's no problem writing secure code in C. You just have to stop being clever and prioritize security above "speed". Your code will probably be fast enough anyway.

If it's too slow, then you probably have an issue with which algorithm/data structure you chose and would have had the same issue in another language.

The biggest issue I have with C today is that you can't trust that your compiler actually generates code that is 1:1 with what you wrote. I'm not talking about UB here, your compiler can actually remove code/checks even though you don't invoke UB.

Then we have UB, I think UB should be removed from the spec completely. There probably was a point in time when leaving stuff as UB was the best option, but today speed is seldom the problem, correctness is.

I no longer work as a C programmer, but I still love the language and I really enjoy writing C code, but I really would like to get rid of UB and have a compiler I can trust to generate code even when I turn on optimizations, and having optimizations off is not an option either, since it can generate broken code as well, so...


> having optimizations off is not an option either, since it can generate broken code as well, so...

Especially when you add this line, you're telling me that what you want is not to program in C but to program in a language which differs from C not in syntax but in semantics, and in otherwise vaguely undefined terms [1] there. And you're mad that compilers implement C instead of your not-C.

I find claims that you can safely write secure code in C hard to believe when you marry them with complaints about compilers not implementing not-C correctly. Especially given that virtually every new sanitizer and static analysis tool to find issues in C code manages to turn up issues in code that is rigorously tested to make sure it passes every known prior tool (e.g., SQLite).

[1] From prior experience, this tends to be best distilled as "the compiler must read the programmer's mind."


It is not possible to remove ub from the spec without turning everything into a pdp-11 emulator, which will sabotage performance on many platforms.

I also don’t believe that a single person on the planet can write a secure c program of meaningful complexity. Static analysis tooling has demonstrated that it isn’t up to the task of saving developers from themselves.


What about SEL4?


Written over many many years by experts of a field, and the end result is at most somewhat complex, nowhere near the complexity of even the monolith SPA of your favorite website.


GP said:

> meaningful complexity

Not, "the most complex". If an OS that can lock down DARPA self-flying helicopter software is not meaningful enough for you....


Less than 10 000 lines of code. But let’s say we accept it as an exception — it is most definitely not the “standard way” of writing C programs.


From GP:

> It is not possible to remove ub from the spec

did not say "it is not standard to remove ub"...


The speed of development was very low, and how many people can check the proofs?


> The speed of development was very low,

Not a part of GP's assertion

> and how many people can check the proofs?

it's not necessary, the proofs are checked using automation. I'm directly taking a shot at this assertion:

> Static analysis tooling has demonstrated that it isn’t up to the task


Just because you have a proof doesn't mean it proves the right thing.


Congratulations. You have won the argument "there is no perfectly secure system", which no one was arguing.


I've got a strong background in formal verification. I do not believe that "formally verified" means "security bug free". In fact, I personally know researchers who have had vulns found in their formally verified code more than a decade after they completed the verification.


I agree, there are lots of outrageous claims out there about "provably secure software" which seem very dubious.

What are your thoughts on SEL4, is it really a breakthrough it is made to be in success of formal verification? Is there a way for users/administrators deploying it to verify themselves authors' claims? Or is it too difficult? I am afraid the latter...

In 2004 Peter Gutmann in his thesis/book criticized the hype around effectivity of formal methods in computer security [1]. Has the situation changed?

[1] https://archive.org/details/springer_10.1007-b97264


Breakthrough? No. Good work? Yes.


I don't think there is any reasonable standard of security that demands perfection.


> I've spent 10 years writing security critical C code. There's no problem writing secure code in C. You just have to stop being clever and prioritize security above "speed". Your code will probably be fast enough anyway.

Are there good examples of what you mean by this? From my own C++ experience, when dealing with c libraries and std::string types, I'll sometimes use the copying api's[0] when passing around std::string::c_str() because I find it easier than worrying about invalidating the returned reference if the string is destructed or modified.

[0]: e.g. https://curl.se/libcurl/c/CURLOPT_COPYPOSTFIELDS.html


Which checks will the compiler remove? If you haven't invoked undefined behaviour then that should be a bug in the compiler


They might be thinking of cases like where C compilers can remove code that zeroes memory holding security-sensitive data. [0][1] The compiler is permitted to reason that this memory is about to be deallocated anyway, so we can elide the memset call.

I can't imagine why a C compiler would remove a non-trivial runtime check though (except undefined behaviour).

[0] https://wiki.sei.cmu.edu/confluence/display/c/MSC06-C.+Bewar...

[1] https://lists.isocpp.org/sg14/2020/12/0482.php


If there were no problem writing secure code in C and C++ we would have a lot fewer vulnerabilities based on some form of memory corruption.


C++ up to and including '98 spec was terrible from security perspective, not a iota better than plain C.


On the contrary,

- proper string and vector types (most compilers allow to enable bounds checking anyway)

- stronger rules for type conversions

- reference types for parameters

- better tooling for immutable data structures

- memory allocation primitives instead of getting sizeof wrong to malloc()

- collection library instead of reinventing the wheel in each project

- RAII

- smart pointers

- templates instead of error prone macros

- namespacing (usefull in large scale projects with prefix tricks)


I'm more interested in the the actual statistics for security vulnerabilities found in C vs. C++ programmes, rather than theoretical benefits one language might have over the other.


Any C++ vulnerabiliy caused by copy-paste compatibility with C is by definition a C vulnerabiliy.


All of which were heavy enough at the time to slow programs down enough that people chose to not use them in favor of faster, more portable C.


That is why Turbo Vision was written in C++ for MS-DOS, Mac OS transitioned from Object Pascal into C++ and Quake made use of Watcom C++.


id's engine was famously C, not C++, all the way through Quake 3.


I don't think there is a justification for the idea that 90s "C++" was going to be substantially different from C. You can call the C files C++ and be pretty much correct. Speculatively ... the OSS community would have converged on the C part of C++. That is the well understood part.


Yep, you see it also in the split away from Qt (C++) to GTK (C).


GTK is polyglot.


GTK provides interfaces to many other languages but it's written in C.


Lol, literally from the GTK home page: "GTK is written in C".




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: