Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Retiring a favourite C++ joke (ignition-training.com)
107 points by kordite on March 17, 2023 | hide | past | favorite | 141 comments


Even the compilers are in on some jokes:

    $ 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 GCC


The old MPW compiler had some gems:

https://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


On template expansion failures, I'd love a modern GCC reporting "your window wasn't tall enough to read this whole error message"


"this error message will take over 200 lines, would you like me to order you a coffee?"


“I have a truly marvelous proof that your code is incorrect…”


I made this compiler joke and received whoping 930 upvotes for it: https://i.redd.it/dp6ixt4ri1hz.png


Ha! It actually took me far too long to get it!


Why is it funny, please explain?


It is the error message you often get when creating a password.


Yes I get that, didn't quite understand why this switching of error message is relevant to the code...


Jokes often work with subverting expectations. In this case you're surprised by a message that doesn't belong and then you remember where it comes from and likely relate it with how frustrating those ever changing rules can be.

That's why the joke works.


I thought it was funny because I've seen similar complaints from linters, e.g. clang-tidy's readability-identifier-length plus readability-identifier-naming, or pylint's invalid-name. (clang-tidy at least is smart enough to exempt loop counters.)


LOL. Loved it


A C++ programmer was arrested for indecent exposure. He was caught exposing his private class in public.


That's what friends are for, right?


Only special friends.


Error: missing member reference


They should build ChatGPT into compilers so you can complain.

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!


ChatGCC

"I'm sorry, as as an ML compiler I can't let you link glibc statically."


And on that day, I finally opened the Monolithic set of x86_64 programmer tomes, and finally figure out how to manually do linking.

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.


hacker disorder :)


I've watching you!


My favorite C++ joke is: Have you heard about the new object-oriented version of COBOL?

It’s called “ADD 1 TO COBOL”


That's more like ++C. You need "ADD 1 TO COBOL RETURNING COBOL"... which elicits another C++ joke: that it would have been nice to get to use the better version, but someone used the wrong operator, so what we have is certainly complicated but probably just more of the same.


The ++ is probably overloaded, and actually formats your hard disk, instead of incrementing a number.

(Just like >> is overloaded to do IO, instead of shifting bits.)


My favorite, best told while among C programmers involuntarily debugging some gnarly C++ is, "Man, I swear, the dude that invented C++ doesn't know the difference between increment and excrement."


C++ makes C bigger, returning the same value.


It's an OK C++ joke, but not great. I could certainly give the author a few pointers...


Yeah, they all just follow a template


Sure, but at a macro level we’re still compiling the same jokes.


Are you sure that's safe?


And I could add a couple of references.


I can only use them after they're free.


Narrator: They weren’t actually free.


How many people read that in Morgan Freeman's voice?


Arrested Development had a narrator: Ron Howard.


Let's make sure, I'll make a callok?


And if that doesn’t work, we can send a malloc?


Narrator: It's at this point Michael realized the futility of C++ and promptly learned Rust over a couple of beers pondering if he will ever survive the oncoming AI apocalypse.


They better be smart ones or it's back to class for you (though I fear you may have to brace yourself for worse than cough this).


I should note here that - while not related to C++ - I almost used .... instead of ... to make this joke extra funny ;-)


My favorite C++ joke is this limerick that has been in the standard for a while:

    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


An other one from the standard:

  void trex(volatile short left_arm, volatile short right_arm);   // deprecated
https://eel.is/c++draft/depr.volatile.type#example-3


This is one of the surviving improvements from JF Bastien's P1152 which was initially successful in deprecating most of the spurious use of volatile from C++ with a view to some day getting in there and actually doing MMIO properly.

Unfortunately 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.


I think [1] explains well why this will be un-deprecated.

[1]: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p23...


Note that P2327 is not what was actually done.

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.


It's one joke Martin. What could it cost, ten dollars?


Ahhh, man. I wish I had thought of that to include in blog text.


    #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 fine

clang++ -Wall -Wextra -Wpedantic main.cc # also compiles just fine


FWIW the behavior of delete on a pointer that isn’t either null or returned from new is undefined.

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.


That this situation is "working as intended" and there are programmers who do not see a problem with that is... well it makes me despair.


What's your proposed alternative? What does the alternative cost? If non-zero, what mechanism would you use to disable it?


I was surprised to see it not mentioned in the post -- the most obvious reason this joke should be retired is not the reference to a television show but rather the modern practice of never using new or delete at all in C++ code. Modern C++ avoids these pitfalls and I think it's been 10 years since I've written the words the new or delete.


I frequently work with companies that have old, large codebases. A key requirement of the training in that environment is that attendees are able to read existing production code. In some cases that's over twenty years old and millions of lines of code. new/delete is just part of that reality. We teach them without encouraging their use.


That's perfectly reasonable. I have fortunately worked on greenfield projects, so don't have to contend with legacy paradigms.


Ah, so you've been doing programming-lite.

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?


> Ah, so you've been doing programming-lite.

I hope you can understand why that's offensive.


Absolutely. I would also not use new/delete in that situation. It would depend on the audience whether they were still taught on a course, sometimes there is, and sometimes there isn't an educational purpose.


That modern pratice is more theory than practice, even on sample code from ISO C++ members.


No, it’s not just theory. Like anything in C++, codebases and their styles widely vary. But my comment holds true for the vast majority of developers I have worked with over the last decade. With the exception of the special “placement new“ operator, it is nearly obsolete to use new and delete.


I suggest browsing around code from Microsoft, Google, Apple,...

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.


Hmm, I was at G until the recent decimation, and would have been surprised to see `new`, especially in new (heh) code, because it immediately raises the question of ownership, which means it costs time for every future reader.

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:...


Now search for C arrays and strings, old style enums, str...() and mem...() functions, C style casts, preprocessor macros,..


That’s called whataboutism.


Nope, it is called experience with large code and teams.


We are talking about one very specific issue, the point of this thread is a joke about new and delete. And your response after evidence services against your position is, “what about all these other things?” Definition of whataboutism.


Nope, the whole issue is about modern C++ in practice versus slideware at conferences.

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.


This is just a petty digression. I won't participate further. Have a nice day.


Finally! One "modern C++" advocate less.


> Dreamer that some day all major systems programming languages will support automatic memory management.

Ironic bio for someone opposed to modern C++ advocates.


If you are going to work with a legacy codebase, then sure. My comment was more about fresh codebases, which are fortunately the only ones I've worked on.


A niche in the C++ world.


I would argue it is not for me at least. In my 2 current C++ commercial products of fair size one has single explicit allocation, the other does not have any.

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.


It's still useful to teach them in my experience. It's hard to introduce smart pointers without explaining the problem they solve (i.e. wrong or missing uses of delete).


I thought the same, modern c++ (>=11) felt like a new start for the language. it's a complete different beast nowdays.


> the modern practice of never using new or delete at all in C++ code

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.


Go is a garbage collector. Smart pointers are not.

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 allocate either on the stack, or on the heap with make_unique and make_shared. Deletion occurs automatically once the object is out of scope.


Why would you respond to a comment about a topic you don't understand and spread false information? You clearly cannot tell the difference between garbage collected language and smart pointers.


Ah, so reference counting is not considered a form of garbage collection any more? Ingenious but somewhat of dishonest.


Smart pointers do not necessarily use reference counting. std::shared_ptr is reference counted, but std::unique_ptr is not. Needless to say that std::unique_ptr should always be the default choice and std::shared_ptr only used when actually needed.


std::unique_ptr is reference counted, it's just that the count only goes up to BOOL_MAX instead of LONG_MAX.


I think you’re making a joke, but reference counting is different than what a unique pointer does. (a destructor is not the same thing as a reference count, even if that reference count is limited as you suggest.)


No, I don't think it's a joke. It's just that when your counter is limited to values of 0 and 1 only, you can optimize it so heavily it almost looks like a different thing entirely: binary semaphores are usually called mutexes, but they're still semaphores.


It was a joke and not a joke, a joke with a kernel of truth.

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.


But it’s not counted, that’s my point.

It’s getting quite pedantic to talk about ones and zeros in this context anyway.


Please show me the counter in std::unique_ptr :-)


Since that counter can only have two values, it's storage is optimized and merged with the underlying raw pointer itself (not unlike Rust's null pointer optimization for enums): non-null value of the underlying pointer also serve to represent the counter's value of 1, and the null value serves to represent the counter's value of 0. The check to not under-decrement, for example, manifests as the null check before calling the deleter on the underlying pointer.


Sigh, I saw this coming. By this definition, every C++ object with a (non-trivial) destructor would be "reference counted". Sorry, but I am not interested in playing word games.


Nope. Only those with "if (this->inner_resource) { /* delete inner resource */ }" inside the destructor could count, others wouldn't.

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.


This is just petty sophism. I won't participate further. Have a nice day.


I can’t upvote this comment enough. The amount of pedantic nonsense on HN these days is disappointing. I’m not sure why I even bother to read comments here anymore.


like the other comment said, std::unique_ptr is not ref counted. Ref counting is one of the ways to implement garbage collection but it is not garbage collection by itself. C++ does not have garbage collection.


C++ does not have garbage collection in the standard library, just as shared_ptr was not part of the standard library in the past. You can currently have optional garbage collection in C++: https://github.com/pebal/sgcl


C++ can do pretty much anything, but that doesn't mean that it’s typical to do so. In practice, you will never see a garbage collector in C++.


You may be surprised. Herb Sutter wants to add optional GC to C++ 'syntax 2'.


Sitter’s idea in that is a different matter entirely.


We are all getting old. College age kids aren't old enough to remember when that show was on the air.


Yes, and I fear that I have not seen or understood a lot of the cultural references/jokes that they would understand.


I am also 29 and I'm old enough to remember Dawson's Creek, but I don't watch a lot of TV so I've never seen it.


If you find yourself with the time, and the inclination, give Arrested Development a go. I thought it was fantastic. I think there is a reason that it always sat a little under the radar. You have to actively watch it. It's not suited to being on in the background.


If you make a friend only because you want to expose your private member to them, you may be a C++ programmer.


There's dozens of people who would get it... DOZENS!


Uses C++. Shortly after:

I've made a huge mistake.


Tobias: You know, Lindsay, as a developer, I have advised... a number of people to explore "modern C++," where everything is RAII, and you never have to write `new` or `delete`.

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.


According to the TIOBE index, C++ is the fourth most popular programming language, and has been around for over 35 years, so easily a couple thousand people. The question is how many of them are on HN (probably dozens).


Either you did not get the joke, or I did not get your joke.


I mean, estimating that there are a couple thousand c++ developers is pretty funny.


It's number one in the TIOBIAS index, though.


yes, I would have thought the "better" version would be

  int tobias[24]; 
  delete tobias;


I'll be honest, I didn't get it at first. I thought initially that it was too complex for the teaching example. And then it clicked. You're rather smart aren't you! I guess 24, or 36, or 48 would have worked!


Yeah, I was thinking the number of never-nudes in the world might closer to 2 dozen than 3 or 4 dozen, but I don't really know!


Hey brother! I always love a good quote back. I've occasionally had a 'there are dozens of us' response in the training room or remote chat. Always makes me smile.


Hey, it actually works!

    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 :)


I assume you have it on x86_64. I'm trying to make sense of that according to glibc implementation details[1] and Sys V/Itanium ABI.

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.

[1] https://sourceware.org/glibc/wiki/MallocInternals


Essentially correct. 33 sets up the pointer to appear to glibc as if it were a small, “normal” 32-byte allocation. The default behavior for glibc free() with a small allocation size will be to put it into the thread cache (tcache), which makes it immediately available to be reused by the same thread.

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.


Weird that undefined behaviour is undefined.

Undefined behaviour is no joke.


> void fn() { int tobias; delete &tobias; } <malloc>: ** error pointer being freed was not allocated

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


Do modern cars even allow you to step on the accelerator and the brake at the same time?


Yes, that’s how you do Launch Control in an Audi.


I guess you technically can’t in an EV with regenerative braking.

(But maybe they do have an actual brake pedal?)


Non-EV driver here; glad I did a search making the "obvious" reply. Surprisingly, "one pedal driving mode" is a thing. Its described as opt-in with a switch or setting, so I guess there's still a brake pedal. Which means some QA techs must have test plans with "switch off, step on brake pedal" and "switch on, step on brake pedal." Or maybe "switch on, step on brake pedal" is undefined behavior and the compiler can optimize it out.


My Kona Electric has brake and accelerator pedals. IIRC if you press both at the same time, the accelerator pedal is ignored.


EVs always have physical brakes and pedal too in addition to regenerative braking. Regenerative braking can't come close to the braking power of disc or drum brakes especially if the battery is full.


Why wouldn't they? The brake simply overrides the accelerator.


Sportier drivers may wish to brake and accelerate simultaneously (rev matching, weight transfer tricks). Normal cars just cut fuel when braking to avoid two-foot drivers burning their brakes.


The other use is for mere mortals to simulate differential lock when it is not there. I've used it couple of times.


I certainly can in my 2019 86.


Maybe he can mock try next?


Better phrasing (and good advice!):

Don't mock try all the time


The biggest c++ joke must be: cout << this << is << what << they << really << think;


It's recommended to use virtual destructors for objects that live on the heap. Say you have a base class pointer to an object of a derived class; with nonvirtual destructors the base class determines the destructor that is called, whereas with virtual destructors it's the derived class that chooses the form of the destructor.


"C++ is to C what lung cancer is to lung".

UNIX haters handboook.


My favorite C++ joke -- "Your friends can see your private parts".


for this kind of errors is why you always leave a comment on your code


This was another one I didn't get straight away, shame on me! Of course, it helps to remember this: https://www.youtube.com/watch?v=BYTNMCWrxEg.


I've read it "Rewriting ..." . You guess in what exactly.


My guess is rust.


[flagged]


You had to be “that guy”, didn’t you?


This place needs rooftop snipers


I've heard The Crusades had ended some time ago...




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

Search: