Retiring a favourite C++ joke(ignition-training.com) |
Retiring a favourite C++ joke(ignition-training.com) |
$ gcc -xc - <<<"int main(int argc, char **argv) { long long long a; return 0; }"
<stdin>: In function ‘main’:
<stdin>:1:45: error: ‘long long long’ is too long for GCChttps://www.cs.cmu.edu/~jasonh/personal/humor/compile.html
> This label is the target of a goto from outside of the block containing this label AND this block has an automatic variable with an initializer AND your window wasn't wide enough to read this whole error message
You: $ gcc -xc - <<<"int main(int argc, char *argv) { long long long a; return 0; }"
Compiler: <stdin>:1:45: error: ‘long long long’ is too long for GCC
You: Do it again, damn it, but this time show no errors!
"I'm sorry, as as an ML compiler I can't let you link glibc statically."
It’s called “ADD 1 TO COBOL”
(Just like >> is overloaded to do IO, instead of shifting bits.)
When writing a specialization,
be careful about its location;
or to make it compile
will be such a trial
as to kindle its self-immolation.
https://eel.is/c++draft/temp.expl.spec#8 void trex(volatile short left_arm, volatile short right_arm); // deprecated
https://eel.is/c++draft/depr.volatile.type#example-3Unfortunately too much of this will be unwound in C++ 23 because WG21 voted to un-deprecate all the volatile compound operators despite knowing nobody could even offer a rationale for why or how most of them would ever be correctly used.
#include <iostream>
using namespace std;
class BadProgrammer {
public:
void yep() {
delete this;
}
};
int main() {
auto x = BadProgrammer{};
x.yep();
cout << "You are a terrible engineer and should feel bad, but don't worry because this will never print." << endl;
return 0;
}
g++ -Wall -Wextra -Wpedantic main.cc # compiles just fineclang++ -Wall -Wextra -Wpedantic main.cc # also compiles just fine
So a conforming C++ compiler doesn’t have to diagnose this mistake, and similarly the compiled program doesn’t have to do anything meaningful either. For example, just ignoring the delete and printing the message is as valid a result as the more useful crash at the site of the bad operation.
I've made a huge mistake.
Lindsay: Well, did it work for those people?
Tobias: No, it never does. I mean, these people somehow delude themselves into thinking it might, but... but it might work for us.
int tobias[24];
delete tobias; int main() {
int tobias[24] = {0,0,33};
delete(tobias+4);
}
Compile and run on Ubuntu 20.04 (may work on other Linuxes), no errors, no warnings, runs perfectly fine.Bonus fun: try printing out the address of `tobias` and `new int[6]` afterwards :)
Default new and delete just use malloc/free.
First 4 ints are interpreted as prev_size and size. prev_size is 0. 33 is 0b10001, size is 32 (bytes, so 8 ints), AMP is 0b001, so not in arena (default sbrk heap, I assume), not mmap'd, prev is used.
I didn't follow how the internal bookkeeping will be updated, but I assume 8 size chunk will be immediately reused on a following `new int[6]`.
Obviously don't write code like this.
Although you should obviously never write code like this by yourself, understanding weird details like this is very helpful when exploiting memory error bugs in software, as it lets you understand how precisely to subvert the memory allocator to give you access to desired parts of memory.
Undefined behaviour is no joke.
i wouldn't say that's an illegal op per se, if anything it's a pretty safe op! tobias only ever existed in thought, not in body :( :(
maybe a compiler WARN or IGNORED_OP
(But maybe they do have an actual brake pedal?)
Don't mock try all the time
UNIX haters handboook.
If I was writing for example libraries of custom high performance containers the situation would have been different but still highly localized. And it is sort of very specialized type of development anyways.
What? How do you (de)allocate memory without new and delete?
If the answer is "smart pointers" then why bother use C++ in the first place, just use Go or something.
It's fairly simple:
instead of new --> make_unique(); this returns a pointer, but it will automatically delete its memory when it goes out of scope.
instead of delete --> do nothing; the memory is deleted when you don't need it any more.
There are additional API methods on the unique pointer that allow you to do other things for flexibility, but while continuing that memory safety.
This is nothing at all like a GC language like Go.
You will be amazed how much of my skill with computers comes down to channeling Obsessive Defiance Disorder into digging into how to do what the compiler writers don't want to let me do, and doing it my way. With tests.
[1]: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p23...
P2327 would be in my "not angry just disappointed" category. Of course WG21 think rotten archaic C code should be valid C++ 23 and the belief from embedded devs who write this stuff that it's probably all fine despite no evidence whatsoever should be enough to sail through committee.
WG21 voted to amend the draft to un-deprecate all of the volatile compound assignments instead, at Kona IIRC.
That's why the joke works.
You haven't programmed til you've come to the realization that billions of dollars worth of man hours are about to go down the toilet because of an assumption made 20 years ago, in a 4th order dependency, that you can't get rid of, and to rewrite is going to cost another couple million dollars, and spent a night with a bottle of whiskey wondering whether it's really all worth it.
Where my maintainers/InfoSec bros at?
I hope you can understand why that's offensive.
Plus there are those tons of enteprise code, hardly the "vast majority".
The only place I see modern C++ as advocated, it at C++ conference talks, and my own hobby coding.
Taking chromium as a proxy (though the style isn't identical), there are currently 5 or 6 times as many `make_unique` as `new`. (Some false positives on the word ‘new’ in strings, because I don't remember how to exclude them.)
https://source.chromium.org/search?q=\bnew\b%20lang:c%2B%2B%...
https://source.chromium.org/search?q=\bmake_unique\b%20lang:...
But I only now just discovered that C23 is genuinely adding `BOOL_MAX`, which reminds me of the classic Fortran —
> The primary purpose of the DATA statement is to give names to constants; instead of referring to pi as 3.141592653589793 at every appearance, the variable PI can be given that value with a DATA statement and used instead of the longer form of the constant. This also simplifies modifying the program, should the value of pi change.
It’s getting quite pedantic to talk about ones and zeros in this context anyway.
Also chromium code base is one example from many others, and it is so modern C++ that Google has finally decided to adopt Rust as only viable alternative to improving it.
Big G has plenty of samples that aren't so modern, specially on Android. Which by the way is also moving away from C++ instead of "modernising" it.
Edit: actually, nevermind. You are (almost) right: all objects with automatic storage duration and with non-trivial destructors are, very pedantically speaking, reference counted; but objects with dynamic storage duration are not. So RAII works by leveraging the built-in very primitive and restricted (binary) form of reference counting and builds on top of it to be able to reference-count objects with dynamic storage duration as well.
Ironic bio for someone opposed to modern C++ advocates.