Yes, you are correct. The point was that C code can keep the ABI intact through (some) data layout changes but vanilla C++ classes cannot I misstated it.
>Good modern practice (c.f. Rust, etc) is to ship LTO'ed mostly-static binaries.
That is the state of play now because Rust does not have a stable ABI. I thought one might be coming but maybe no one's working on it. It's unfortunate because it would be really nice to have binary crates with signing.
>hopefully in a few years everyone will switch to snap / flatpack / appimage to finally reach a sane application distribution model on Linux.
Snap has a while to go before it can be adopted fully. Images are enormous, they take a long time to load, and they don't respect (or don't understand) hidpi settings. I tried to use it for spotify and telegram-desktop and other applications but they just don't work that well.
>it much harder to hack your way out of things when it's 3AM and everything is crashing and you have 5 minutes to fix things before heads start to roll.
Absolutely but it comes from enormous systems like Windows where changing a library and breaking ABI means recompiling Everything. And these compilation jobs are often 'overnights'.
Ctors/dtors can break ABI as well: https://gcc.godbolt.org/z/XAx00v
It sure sounds to me like modern practice as you've defined it is that when a component has a security vulnerability you're not going to patch it. It's going to be statically linked and running in a container image maybe created by somebody else and you'll have no idea it's there.
Yes, it theoretically lets you ship a patch version bump containing security fixes for the few languages with a stable ABI. But even ignoring the deluge of unpatched IOT garbage running seriously out of date kernels - nevermind userspaces - how do you ship that version bump of your library to your Windows users? Your OS X users? iOS? FreeBSD? RedHat? Android? Mint? Debian? PS4? Redox? Xbox One? Solaris? Switch? I've dynamically linked into PuTTY before - a good 'ole C codebase - and I still had to rebuild and redeploy myself when a security patch landed.
Meanwhile, an updated package on crates.io can change deps.rs badges, or trigger dependabot - optionally auto-merging the pull request if CI passes, or altering you to the build failure and need for manual action if that "patch" version broke things. Rustsec and cargo audit/geiger/crev are all hideously platform independent ways to catch problems. My patches to an unsound Rust crate can automatically land on your WASM-enabled website if you have things so configured.
What Go and Rust do (by default) is only useful for internal software that you have full control of (both in source and in updates), but it is definitely not "good practice" for general software distribution.
Going fully static (Go) or mostly static (Rust) means your users/clients cannot update dependencies easily. Users will suffer when the vendor is not replying as quickly as they would hope for (which is not a pleasant experience at all, specially if you run server software) or when they simply discontinue the software (cf thousands of games). Then there is the usual duplicated code pages with less effective cache utilization etc. (which is a minor issue nowadays but if everything is a 100 Mo Electron copy it starts being painful).
Linux packaging is interesting, since the delivery model of gratis distributions often have no such guarantees. Thus one may indeed experience difficulties at any moment after a recent upgrade due to that model. In that case, the complexity lies within upstream and distro, a shared responsibility that the distro should reconcile but may fail to do in minute detail.
Modern methods involve a pipeline, and no rogue upgrades that haven't passed multiple stages of tests and security checks.
If they don’t work, they are broken. Of course it can happen, but the opposite approach means never being able to do it.
> If there are security issues, 99% of that should rather be solved by safe language usage and security perimeter or encrypted channels
There is no mainstream language or operating system out there that solves "99% of security issues" unless you are talking about formally proven systems etc.
> The deliverables are provided and guaranteed by the vendor.
As I explained in the GP, this only happens for systems with support contracts.
For most software out there, this isn’t the case. Mainstream software vendors don’t guarantee you anything at all, for good reasons.
> Modern methods involve a pipeline, and no rogue upgrades that haven't passed multiple stages of tests and security checks.
That is not "modern". That is how it has always been done since the 80’s. Again, for software properly supported.
I am not sure why you talk about "rogue" updates, since nobody has mentioned such.
My experience as a Linux user is that I suffer even more from some minor update in /usr/lib/libwhatever.so suddenly breaking some feature in software that I use to do my job / have fun, which wouldn't happen at all if that software was self-contained.
The benefit of dynamically linking is that you (as a user) or upstream (most likely) can fix those issues you point out, including future ones.
Being self-contained simply means updates aren’t forced into it, which is a good thing and I agree with it.
I didn’t downvote you, by the way, since the point you make is valid.
definitely not all, only things that change the layout. adding a non-virtual method does not break ABI at all for instance.
> Contrast with C where you would forward declare a struct in the header and pass that around while the definition is hidden in a .c file. This means changes to the size of the structure don't matter because all calling code ever sees is a pointer. (True data hiding!) It's called an opaque pointer and many many libraries use this pattern. e.g. libcairo.
Does this have a point in 2020 ? Good modern practice (c.f. Rust, etc) is to ship LTO'ed mostly-static binaries. Such hiding is only relevant for legacy things such as what Linux distros obstinates themselves in doing for their userspace - hopefully in a few years everyone will switch to snap / flatpack / appimage to finally reach a sane application distribution model on Linux.
I'd definitely say PIMPL is 100% an anti-pattern in every possible case. It forces more memory allocations, and makes it much harder to hack your way out of things when it's 3AM and everything is crashing and you have 5 minutes to fix things before heads start to roll.