Reading through your comments the only take-away appears to be that you just really don't like C for whatever reason.
C is a perfectly fine language for tasks of all kinds. The fact that it expects programmers to take greater care when using it is not a reason enough to dismiss it as a general-purpose language. Not everyone needs (or wants) to ride a tricycle wearing knee pads and a helmet to get from A to B.
I agree that "straight C" is not the best choice anymore... but C++ isn't great either. It inherits most of C's weaknesses and for libraries, it makes it very difficult to use the code from languages other than C++. By making a library in C++ you are basically limiting it to being used only in C++ projects. (Yes, wrapper generators for C++-to-whatever exist, but my experience with using e.g. Qt from other languages has always been pretty terrible).
Even in 2019, the C ABI is the one universally agreed-upon cross-language ABI for languages compiled to native code.
However given that at least C++ does support ways to tame C, after all the whole purpose was for Bjarne never to repeat his Simula into BCPL rewrite experience ever again, it is up for security conscious to decide what legacy they want to leave, when the option is between both those languages.
On the other hand maybe C should be used to write Skynet, so that we stand a chance.
That may be so, but the central thesis of the article is that C is the still the appropriate language in which to write libraries for interoperation. If you believe otherwise, I suspect that a rebuttal of the author’s arguments in favor of C would be well-received as a top-level comment here— there seem to be a lot of people that agree with you, but nobody has yet stated why they hold that opinion.
Sure, first of all there is no such thing as C ABI, only OS ABI.
C ABI happens to be the mixed up with OS ABI, on OS written in C like UNIX clones, on mainframes, and other competing OSes that isn't the case, because they use other systems languages on their stack, or even some kind of bytecode based interoperability format.
However since the context here is game libraries, C ABI == OS ABI pretty much applies everywhere (except WebAssembly or Android JNI) and lets leave at there.
Since C++98, writing a library in C++, even if exposing it as extern "C", provides the following benefits for the quality of code implementation:
- less implicit conversions
- use of reference types instead of pointers for memory accesses we can be sure are never allowed to be null
- use of namespaces instead of Assembly style programming of having to come up with prefixes for code organization
- bounds checking for strings, vectors and other related data structures provided one uses the library types. They can even be left turned on for release mode, if the profiler shows there is no visible impact on hot paths
- use of RAII to manage library internal state and reduce leak occurrences
- ISO C++ working group is actually striving for reducing the amount of UB from its 200+ use cases, unlike ISO C group
- strong typed enums introduced in C++11 don't have implicit conversions and must map to their underlying types
- type safe compile time code execution, specially helpful in games, used for stuff like generating trigonometry tables
- templates as replacement for pre-processor magic that eventually goes subtly wrong when the #include order gets misplaced or too few parenthesis are used
If this still sounds absurd, well all major C compilers are now implemented in C++, Microsoft rewrote their C standard library in C++ with extern "C" entry points, Android NDK is actually implemented in a mix of C++ and Java (via JNI) also using extern "C" calls.
> but nobody has yet stated why they hold hat opinion.
I did, in my first comment.
C++ namespaces lead to much more readable code, compared to these prefixed names.
C++/11 scoped enums eliminate a class of bugs: when you have many different constants on the API surface, multiple functions accepting them, and erroneously use the constant of a wrong function. Example:
enum Lod { Low, High };
enum SomethingElse { Other };
void setLoD( enum Lod v );
void bug()
{
setLoD( Other );
}
Especially with this expanded commentary, you do show some advantages of C++ over C, but you have only addressed the advice for how to proceed once you’ve chosen C and not the author’s reasons for preferring C to C++ (or any other language):
— Every language out there has a way to call into C
— If your code is slower than C, someone will rewrite it in C.
— If your library is written in C it means it can be used on any OS, console or mobile device and even on the web.
— Not everyone wants to use C++ (some prefer C).
— It is easier in general for a C++ user to use a C library than it is for a C user to use a C++ library.
— C++ is not as easy to write wrappers for in other languages.
— Unless you limit which C++ features you use (to the point where you are pretty much left with C) a lot of people won’t be able to use your library.
PS. If your original comment had been phrased the way you put it here I might have made the same comment, but I would not have downvoted it. Here, you’re at least providing some supporting evidence for your assertions which makes it a much more valuable contribution to the conversation.
> If your code is slower than C, someone will rewrite it in C.
When used correctly, C++ is not slower than C. Sometimes faster, a classic example is C qsort versus std::sort.
> If your library is written in C it means it can be used on any OS, console or mobile device and even on the web.
C++ is good in that regard. I know only 1 mainstream platform where C++ adds significant friction compared to C, that’s iOS, because their objective C is a superset of C. The rest of them (Windows, Linux including embedded, game consoles, android) support C++ just fine.
> Not everyone wants to use C++ (some prefer C).
Most people are OK with C++, especially in the context of game development.
> to the point where you are pretty much left with C
No, not with C. Namespaces and scoped enums are awesome.
Another thing, inside the implementation of the library, you can use whatever C++ language features you please, even the features that would be inappropriate when exposed at the API surface of the library. For example, MS implemented parts of their C runtime library with C++ classes, RAII, lambdas and templates, eliminating duplicated code for char/wchar_t routines. Obviously, you don’t need C++ to consume that library, just C is enough, but it’s implemented in modern C++. On my system, that source is in "C:\Program Files (x86)\Windows Kits\10\Source\10.0.18362.0\ucrt\stdio\output.cpp".
I once forked a C library, porting some parts to C++ in the process: https://github.com/Const-me/nanovg/ I’ve retained original C API, only used C++ in the implementation.
Then I’ve got an e-mail from a developer who asked a few things how to back port my changes to C. I answered their questions, but I was curious why. They replied it’s because Objective C and iOS. Personally, I haven’t been developing for iOS for several years, but I don’t think people would do such things for lulz.
That developer must be misinformed. I have been developing a native component that needs to interface with C++ APIs from the app and Objective C APIs from iOS. The only thing you need to remember is to not mix exceptions from C++ and Objective C. The object models are also incompatible, but the compiler prevents you from mixing them.
Also, if C++ is only used in the library implementation... you wouldn't even need Objective-C++ unless you needed to add Objective-C API calls to the library's own source files. Otherwise, you could just compile the library's source files as regular C++, and link them together with your Objective-C code. This works exactly the same way as combining C and C++, and Xcode (the IDE) has no issue with it. So it seems very likely that the developer was misinformed.
It actually extremely easy to write C++ wrappers for other languages. Examples I‘m familiar with are pybind11 (similar to boost python) and the node C++ API. That other languages don’t have similarly convenient libraries is entirely their own fault.
Are you looking for a safe way to use your computer? Turn it off.
Other than that, I'm not surprised the file in question is C. Even ignoring the fact that it was you to get the link. And even ignoring that it's about a security problem...
Other than that, from a user perspective, software written in C is among the most reliable software I'm using. I'm looking at Linux, vim, xterm and so much of the infrastructure that I don't even know by name.
Some people value "security" more than they value the beauty of a nice, a maintainable, or a practical program. That's ok as far as I'm concerned...
Sure there is. But never be blinded, Linux is very performant and rock solid from an end user's viewpoint. Sometimes it helps putting things into perspective.
What do you think are the monetary losses by unmaintainable software, resulting in bad and extremely unsafe practices (not related to memory, but...) like in my link? What do you think are the monetary losses from developers going mentally ill because they don't understand and don't like the shit they're doing?