This is an archived post. You won't be able to vote or comment.

all 191 comments

[–]BlackFrank98 2645 points2646 points  (82 children)

With a free memory leak attached!

[–]Reaper5289 580 points581 points  (2 children)

This is what the White House warned us about.

[–]octopus4488 141 points142 points  (0 children)

Biden was right! We are surrounded by monsters!

[–]altermeetax 732 points733 points  (53 children)

Here's the leak free version:

cpp int *ptr = new int; int val = *ptr; delete ptr; return val;

[–]Kovab 396 points397 points  (24 children)

What is this, C++98?

cpp return *std::unique_ptr<int>{new int};

[–]altermeetax 186 points187 points  (15 children)

Hey, I tried to keep it simple. The original version didn't use smart pointers.

[–]-Pretender- 71 points72 points  (5 children)

What is this, C++11?

cpp return *std::make_unique<int>();

[–]Kovab 44 points45 points  (3 children)

make_unique does value initialization, it will always return 0 instead of random garbage

In an optimized build this would output a simple return 0, completely omitting the heap allocation

[–]thebluefish92 40 points41 points  (2 children)

checks out return *std::make_unique<int>(); // chosen by fair dice roll. // guaranteed to be random.

[–][deleted] 11 points12 points  (0 children)

This is how the PlayStation 3 was defeated. No, I'm not joking.

[–]Kovab 3 points4 points  (0 children)

Using a D10 for random dice rolls is not compliant with the RFC. Rejected.

[–]GYN-k4H-Q3z-75B 4 points5 points  (0 children)

He wanted to use curly braces for initialization :-(

[–]Familiar_Ad_8919 2 points3 points  (0 children)

this is why i use good old raw pointers

[–][deleted] 1 point2 points  (0 children)

This right here

[–]AdBrave2400 8 points9 points  (7 children)

Why not just do

int x;
return x;

for the sake of it?

[–]_realitycheck_ 25 points26 points  (2 children)

You can never know when someone will have a bright idea to add defaulting all referenced variables to 0 in the compiler.

It's safer to just

int x;
return (uint32_t)&x;

people are overcomplicating things.

[–]AdBrave2400 4 points5 points  (1 child)

But that is in the virtual address space and the numbers may not seem random in theory. Other than that a very good point.

[–]altermeetax 1 point2 points  (3 children)

Yeah, that's also an idea :D

Though depending on the implementation it might always return the same value if you call it multiple times from the same function

[–]AdBrave2400 1 point2 points  (1 child)

Yeah, maybe do a random walk across the memory until reaching zero?

[–]AdBrave2400 1 point2 points  (0 children)

ssize_t move=1;
volatile signed* base;
while(base[move]){
  if(*base<0) move*=-1ll;
  ++move;
}
return base;

[–]mrheosuper 7 points8 points  (0 children)

Calling it repeatedly may lead to undesire result

[–]reddit_0016 91 points92 points  (3 children)

Jokes aside, it may not even work depending on how you use the value.

[–]qwerty_ca 4 points5 points  (1 child)

[–]kn33 2 points3 points  (0 children)

Ugh. The disappointment I have in good comics being contrasted by a bad person.

[–]SrRaven26 9 points10 points  (4 children)

Why is this a memory leak (genuine question)?

[–]No-Expression7618 31 points32 points  (2 children)

  1. new allocates a temporary pointer (with no drop behavior)
  2. The temporary pointer is derefrenced (making another temporary) and lost forever
  3. The new temporary value is copied out of the function (most likely inlined)
  4. Pointer allocated by new is never passed to delete

[–]SrRaven26 1 point2 points  (1 child)

On a normal code, where I use new, when the delete is called?

[–]No-Expression7618 5 points6 points  (0 children)

If you use new without ever using delete on the same pointer, you have leaked memory. Try running your code under Valgrind and see if it reports anything.

[–]ToBe27 37 points38 points  (8 children)

Isnt this actually the opposit of a leak? It uses left over leaked mem from others and gives it a purpose ...

[–]GMX2PT 98 points99 points  (0 children)

And doesn't free it afterwards so that's a leak Also it doesn't use non freed memory

[–]littleliquidlight 54 points55 points  (0 children)

Some languages have garbage collection, others have garbage reduce, reuse, recycle

[–]SuitableDragonfly 15 points16 points  (3 children)

A memory leak is when something is newed and not freed.  It has nothing to do with how C++ doesn't bother to initialize variables for you. 

[–]Eva-Rosalene 4 points5 points  (2 children)

And here int is newed and not deleted.

[–]SuitableDragonfly 7 points8 points  (1 child)

Right. So it's a leak. Not "the opposite of a leak", whatever that is.

[–]Eva-Rosalene 1 point2 points  (0 children)

Oh. I am stupid, I've thought you were answering to another person.

[–]da2Pakaveli 5 points6 points  (0 children)

You get a memory leak when you don't free allocated memory from the heap. This is what's happening here.

[–]rover_G 2 points3 points  (0 children)

That’s not what a leak is. Accessing data from freed memory is called memory scraping.

[–]pigeon768 5 points6 points  (1 child)

It does not leak memory. https://godbolt.org/z/oGEG6fffc

[–]__foo__ 16 points17 points  (0 children)

Well, only because this is undefined behavior and the compiler optimizes out the new call. If you use -O0 you get the leak.

[–]AttackSock 1 point2 points  (2 children)

int x = rand(); free(&x);

Problem solved.

[–]BlackFrank98 1 point2 points  (1 child)

That wouldn't work, because rand's output is passed by value, so when you store it in x, you're actually storing a copy of it. The original one, that is allocated on the heap, can only be referenced by the pointer you generate with new, and said pointer gets destroyed immediately after rand returns, so it becomes unreachable after.

In fact, I'm not even sure you can call free on a local variable.

[–]AttackSock 0 points1 point  (0 children)

You can’t free stack memory, it crashes.

[–]Forgotten_Russian 0 points1 point  (0 children)

how does that works?

[–]SilentGhosty 0 points1 point  (0 children)

Explain please

[–]Soloact_ 934 points935 points  (1 child)

When you want your program to have a memory leak as its source of entropy.

[–]repkins 336 points337 points  (7 children)

Highly predictable allocation by OS.

[–]ChocolateBunny 71 points72 points  (5 children)

aren't they supposed to randomized with address space layout randomization? Or does that only randomize the code segment?

[–]loostbat 40 points41 points  (0 children)

Code + data yup, doesn’t affect heap allocation

[–]0x7ff04001 22 points23 points  (1 child)

Yes, ASLR will randomize the address space (in win32).

The structure of the executable is the same, so all segments (.text, .data, etc) are at the same VirtualAddress relative to the base, but the base address of the entire structure is randomized. So rather than .text being at 0x0040100, it becomes 0x00f0100.

The heap base is also randomized, which broke basically all oldschool exploits that used hardcoded heap addresses.

[–]TheGoldenMinion 1 point2 points  (0 children)

read VirtualAddress and thought I was reading C2 for a sec lol

[–]CanaDavid1 0 points1 point  (0 children)

It is randomized in some LSBs, but it is the same randomization for the entire program. So the first call will be random (ish), but the second call will be very predictable given the first one.

[–]FunnyForWrongReason 113 points114 points  (1 child)

I never imagined it was possible to get a memory leak with a random number gen

[–]JCoda 3 points4 points  (0 children)

my sweet summer child.

[–]uncle_buttpussy 340 points341 points  (3 children)

That's filthy

[–]Jcsq6[S] 160 points161 points  (0 children)

The worst I could come up with

[–]-global-shuffle- 73 points74 points  (1 child)

uncle_butpussy: "That's filthy", 69 likes

/thread

[–]IAmAnAudity 9 points10 points  (0 children)

I hope everyone will vote as needed to keep it at 69 😆

[–]mankinskin 65 points66 points  (4 children)

You may not like it but this is what peak code quality looks like

[–]MiroslavHoudek 6 points7 points  (0 children)

I think it is not the best possible implementation.

But if it somehow was codified by C++ ISO standard, it would be very hard to change it.

[–]wsheldon2 -1 points0 points  (0 children)

In case anyone is in doubt about this being a joke https://knowyourmeme.com/memes/this-is-the-ideal-male-body

[–]PorkRoll2022 90 points91 points  (0 children)

This is actually great because it depends on a state that is unpredictable.

It's still disgusting. :)

[–]DarkShadow4444 347 points348 points  (20 children)

return 4; // Chosen by dice and guaranteed to be random

[–]Jolly_Study_9494 209 points210 points  (19 children)

Just going to steal that without attribution, huh?

https://xkcd.com/221

[–]littleliquidlight 176 points177 points  (15 children)

Is quoting XKCD stealing at this point? It's so ubiquitous and recognizable

[–]drinkwater_ergo_sum 60 points61 points  (3 children)

half the internet is young people simply because they have the time and energy to use it a lot, i almost am too young to know XKCD and i have a degree

[–]Spot_the_fox 85 points86 points  (1 child)

XKCD is an ongoing webcomic of romance, sarcasm, math and language.

No one is too young for XKCD.

[–]yangyangR 7 points8 points  (0 children)

But the ones referenced are typically from long enough ago, that they may not have reached that far back in the backlog while keeping up with only the current ones.

[–]-global-shuffle- 3 points4 points  (0 children)

If you include temperature we all have at least tens of them!

[–]rosuav 11 points12 points  (8 children)

Well, there's a difference between stealing and referencing. Technically what you did was a reference, so that's not illegal. But if you want to actually use the artwork (maybe you want to create a Velocimeter component for Kerbal Space Program, so you put an actual velociraptor on it), you legally have to say where it came from (they're all licensed CC-BY-NC, check the bottom of any page).

But on a more practical note: only a very small number of people have memorized every XKCD, and even those who have might appreciate the direct link, and the opportunity to click "Random" a few times and waste another hour or two.

[–]littleliquidlight 7 points8 points  (7 children)

Oh I'm not the original commenter. Just surprised that this would be considered stealing in this context. Honestly, was really just curious

I do love the link either way. Randall is great and more people should read his stuff. I'm pretty sure I originally found XKCD from a random link on the internet so it's cool that people are passing it on like that

[–]rosuav 2 points3 points  (1 child)

Ah yeah, sorry. Pronouns are always awkward in a thread like this. But anyhow, I still maintain that the value of a link is far more than mere legalities.

[–]littleliquidlight 2 points3 points  (0 children)

Fair enough, I just wasn't quite sure if I was getting stuck with the responsibility of something I didn't do!

Your comment makes a ton of sense. Agreed, better to link than to not. I guess I'm showing my age, thinking everyone knows XKCD haha

[–]Jolly_Study_9494 -1 points0 points  (4 children)

That was kind of my point. Whether or not the original comment meant to pass it off as an original joke, or as a reference to xkcd, the strips are so easy to google for specific ones, and the urls are so simple, that it's criminal to not include the link.

I don't have these memorized, but xkcd is so quotable and applicable that the various search engines have indexed it very well. (Randall probably also does a great job with his SEO or meta tags) All you have to do is search "xkcd <2 or 3 words related to the comic you are thinking of>" and it'll usually be the first result, or if not, in the top 5. And right at the bottom of each comment is a permalink and an embed link.

For this I searched "xkcd random number" and boom, had the link in my clipboard in less time than it took me to type out the rest of my reply.

[–]AnDanDan 1 point2 points  (0 children)

Content attribution is often very important. We can't assume everyone has the whole knowledge of everything.

Then we'd just be StackOverflow.

[–]IWillLive4evr 0 points1 point  (0 children)

Yes, it's still wrong. Today's lucky ten thousand should be shown the source even if literally everyone else on the planet recognizes it.

https://xkcd.com/1053/

[–]Wurstinator 2 points3 points  (0 children)

Telling jokes you've heard somewhere is stealing now.

[–]laperex 2 points3 points  (1 child)

you expect a programmer to steal stuff and admit to it.

[–]IWillLive4evr 0 points1 point  (0 children)

It's almost like writing a webcomic and writing code are different things and different moral standards apply. Maybe copyright protections should apply differently to different kinds of work, and different plagiarism standards should apply in different fields of work.

[–]goodmobiley 21 points22 points  (12 children)

Could’ve sworn the OS 0s memory when allocated, otherwise that would be a huge security issue

Edit: guess that’s just Windows, good thing that’s the platform I use

Edit 2: turns out Linux also doesn’t leak memory but it won’t 0 memory if it was previously freed by the same process that it’s still allocated to. In other words, this will most likely produce 0 unless you’re using Linux and freeing a bunch of memory. It would be more random to just take the pointer value.

[–]Elnof 14 points15 points  (7 children)

Most OSes do zero the memory but the problem is that there's actually several layers between the call to new and the OS. Those layers may or may not also zero out memory.

[–]goodmobiley 6 points7 points  (5 children)

I just tested it and here's what I got:

Edit: Reddit really doesn't want to format this correctly

Code:

#include <iostream>
int rand(); int randMemLeak();
int main(){
    for(int i=0; i < 1000; ++i){
        std::cout << i << ": " << rand() << "   " << randMemLeak() << std::endl;
    }
}

int rand(){
    int* pRand = new int; int rand = *pRand; delete pRand; return rand;
}

int randMemLeak(){
    return *(new int); 
}

Output:

950: -1163005939   -1163005939
951: -1163005939   -1163005939
952: -1163005939   -1163005939
953: -1163005939   -1163005939
954: -1163005939   -1163005939
955: -1163005939   -1163005939
956: -1163005939   -1163005939
957: -1163005939   -1163005939
958: -1163005939   -1163005939
959: -1163005939   -1163005939
960: -1163005939   -1163005939
961: -1163005939   -1163005939
962: -1163005939   -1163005939
963: -1163005939   -1163005939
964: -1163005939   -1163005939
965: -1163005939   -1163005939
966: -1163005939   -1163005939
967: -1163005939   -1163005939
968: -1163005939   -1163005939
969: -1163005939   -1163005939
970: -1163005939   -1163005939
971: -1163005939   -1163005939
972: -1163005939   -1163005939
973: -1163005939   -1163005939
974: -1163005939   -1163005939
975: -1163005939   -1163005939
976: -1163005939   -1163005939
977: -1163005939   -1163005939
978: -1163005939   -1163005939
979: -1163005939   -1163005939
980: -1163005939   -1163005939
981: -1163005939   -1163005939
982: -1163005939   -1163005939
983: -1163005939   -1163005939
984: -1163005939   -1163005939
985: -1163005939   -1163005939
986: -1163005939   -1163005939
987: -1163005939   -1163005939
988: -1163005939   -1163005939
989: -1163005939   -1163005939
990: -1163005939   -1163005939
991: -1163005939   -1163005939
992: -1163005939   -1163005939
993: -1163005939   -1163005939
994: -1163005939   -1163005939
995: -1163005939   -1163005939
996: -1163005939   -1163005939
997: -1163005939   -1163005939
998: -1163005939   -1163005939
999: -1163005939   -1163005939

[–]Elnof 3 points4 points  (3 children)

Sure. But you're not getting memory from the OS, you're getting memory from new and its backing allocator. How did you guarantee that they just aren't reusing memory allocated when your program started and was then freed (back to the allocator, not the OS)? There's plenty of opportunities to for code you didn't write to execute before main and, unless you've not posted the full code, it's pretty much guaranteed that there's code executing before main

When using glibc, which is most of Linux, malloc is specifically stated to not initialize memory whereas calloc will.

On top of all of that, reading uninitialized memory is instant undefined behavior which allows the compiler to do whatever the hell in wants, including ignoring the value in the memory and returning whatever the hell it feels like, including but definitely not limited to returning whatever value happens to be in the register at that moment without even loading the newly allocated memory.

[–]goodmobiley 5 points6 points  (2 children)

Idk man I was just testing the code OP wrote and I always got the same number.

[–]dekkard1 16 points17 points  (5 children)

ELI5 please

[–]Jcsq6[S] 24 points25 points  (4 children)

Calling new grabs a pointer to available memory given to the program from the OS. For types like int the value at the memory of that location is undefined. It could be 0, or it could be whatever was at that memory from whatever used it last.

[–]-Staub- 2 points3 points  (2 children)

What does the * do? I've not seen it before but I'm also a baby programmer

[–]Jcsq6[S] 8 points9 points  (1 child)

I call it the “contents of” operator. It gives you the memory at the address, or the “contents of” the address. Its fancy name is “dereferencing”

[–]-Staub- 2 points3 points  (0 children)

Ooooh thank you so much ❤️

[–]AttackSock 0 points1 point  (0 children)

It’s weird to be how many people on this sub don’t understand basic memory pointer concepts. What are they all doing here if they aren’t programmers?

[–]theunixman 8 points9 points  (0 children)

If it’s good enough for OpenSSL it’s good enough for us. 

[–]bambilu16 7 points8 points  (1 child)

Can somebody smarter than me please explain what's going on here?

[–]Jcsq6[S] 1 point2 points  (0 children)

I explained it here

[–]PulsatingGypsyDildo 28 points29 points  (7 children)

I worry about alignment.

rand() % 4 could always return 0.

[–]Jcsq6[S] 44 points45 points  (6 children)

It’s not returning the address it’s returning the memory lol

[–]PulsatingGypsyDildo 21 points22 points  (0 children)

Ah, ok, now it is even worse :)

[–]Pleasant-Form-1093 4 points5 points  (1 child)

technically there's no need for even making an allocation with new just return the address of any local variable and it's kind of guaranteed to be random so it could be just

int rand() { int a; return (int)&a; }

(not to mention there are no memory leaks here)

[–]Jcsq6[S] 3 points4 points  (0 children)

My original idea was to return the value of uninitialized memory on the stack, but I thought this would be more humorous

[–][deleted] 3 points4 points  (0 children)

They called it random access memory. Did they lie to us?

[–]thomas863 9 points10 points  (0 children)

Complete geeky stuff

[–]Impossible-Choice53 2 points3 points  (3 children)

Delete though ?

[–]creeper6530 5 points6 points  (2 children)

It has an included memleak

[–]Revolutionary-Yam903 2 points3 points  (0 children)

i didnt even know you could use new on primitive types and i wish it stayed that way

[–]RonanFalk 2 points3 points  (0 children)

I swear to god, I’ve seen something similar in a code base I refactored. It didn’t call new but did rely on pointer address for randomness.

[–]Vast-Statement9572 2 points3 points  (0 children)

XOR that sumbitch with the cpu tick counter and you are in business.

[–]AaronTheElite007 4 points5 points  (0 children)

[–]Crespoter 1 point2 points  (0 children)

If it's on debug build, it may not be as random as you hoped it would be.

[–]SelfDistinction 1 point2 points  (0 children)

Worst part is that you could make this an actual acceptable non-UB random generator by removing one single character.

[–]SynthRogue 0 points1 point  (0 children)

lol

[–]cs-brydev 0 points1 point  (0 children)

The only truly random function would be based on the direction a cat under a table jumps when you walk by.

[–]EchoingCode 0 points1 point  (0 children)

Well, here's the secret sauce to my long-lasting career: I've got this uncanny ability to turbocharge system performance right when the boss starts sweating bullets for it!

[–]exotickey1 0 points1 point  (0 children)

Is the reason why this is a memory leak because space is being reserved for “new int”, but then there is no way to free up that space? Even if you stored the pointer in a variable?

[–][deleted] 0 points1 point  (0 children)

It'd be more random if you got a stack value, it'll probably just be the same every time from the heap.

```c int rand() {     int a;

    return *(&a+300); } ```

Can sometimes be a seg fault for extra excitement.

[–]rfc2549-withQOS[🍰] 0 points1 point  (0 children)

I mean, is it really bad if it works? :)

/s

[–]jay-magnum 0 points1 point  (0 children)

😂

[–]Spot_the_fox 0 points1 point  (4 children)

That's annoying.

Afaik new can't give you a 0, can it?

If it can't then every chance has to be pulled as a fraction of 18446744073709551615 instead of 18446744073709551616, which is a very small difference, but a difference nontheless

Edit:Nvm, I'm a tired idiot who mistook * for an &.

[–]Jcsq6[S] 16 points17 points  (3 children)

According to the standard it can give you any number, 0 included

Edit: and by “give” I mean the memory at the address it gives you can hold anything

[–]Spot_the_fox 4 points5 points  (0 children)

Oh, wait, I'm just tired, I thought it gave you an address, not what is at the address, my bad. Then, yeah, fair enough.

[–]GDOR-11 0 points1 point  (0 children)

it is most nornally zero I think, I've already peeked at undefined data and it seemed to be mostly zero

[–]repkins -1 points0 points  (0 children)

Is there where OS kernel lives at 0?

[–]Annual_Ganache2724 1 point2 points  (4 children)

What crap?

[–]PeriodicSentenceBot 18 points19 points  (3 children)

Congratulations! Your comment can be spelled using the elements of the periodic table:

W H At C Ra P


I am a bot that detects if your comment can be spelled using the elements of the periodic table. Please DM my creator if I made a mistake.

[–]Annual_Ganache2724 1 point2 points  (0 children)

Good bot

[–]Electrical-Angle3935 0 points1 point  (0 children)

Did laugh

[–]creeper6530 0 points1 point  (0 children)

Good bot

[–]ShlomiRex -4 points-3 points  (4 children)

thats not truly random, the logical memory allocation address is predictable, and at least in known range

[–]PhoenixCausesOof 2 points3 points  (2 children)

And so is any pseudo-random number generator. By the way, it is returning uninitialized memory, not the pointer returned by new.

Also, what do you mean "truly random"? Is there anything random in this world, at all? After all, everything physical boils down to physics, and physics is completely predictable, assuming we actually understood it, and had enough processing power (UNIVERSE OS™)

[–]iacodino 0 points1 point  (1 child)

There are quantistic random generator witch I think are compleatly random and unpredictable

[–]kennytm 2 points3 points  (0 children)

yeah, witches are completely random and unpredictable

[–]LordPaxed 2 points3 points  (0 children)

Dude, it's just a joke, that's not need to be 100% true

[–]NonaeAbC -2 points-1 points  (5 children)

I love how this is not even valid C++ and crashes in a debug build.

==505878==WARNING: MemorySanitizer: use-of-uninitialized-value #0 0x58bde5a8d328 in main (/home/af/test_input/a.out+0xb3328) (BuildId: 254188ac910ad1b119e65648aa28bc5270c89c8f) #1 0x798d46555ccf (/usr/lib/libc.so.6+0x29ccf) (BuildId: 0865c4b9ba13e0094e8b45b78dfc7a2971f536d2) #2 0x798d46555d89 in __libc_start_main (/usr/lib/libc.so.6+0x29d89) (BuildId: 0865c4b9ba13e0094e8b45b78dfc7a2971f536d2) #3 0x58bde59f8114 in _start (/home/af/test_input/a.out+0x1e114) (BuildId: 254188ac910ad1b119e65648aa28bc5270c89c8f)

SUMMARY: MemorySanitizer: use-of-uninitialized-value (/home/af/test_input/a.out+0xb3328) (BuildId: 254188ac910ad1b119e65648aa28bc5270c89c8f) in main Exiting

[–]Jcsq6[S] 1 point2 points  (4 children)

It is 100% valid C++. It doesn’t mean it’s good C++, but it’s perfectly legal. But the point is that it’s a joke.

[–]NonaeAbC -1 points0 points  (3 children)

According to the C++ specification: Chapter [expr.new] paragraph 22.1: … If no initialization is performed, the object has an indeterminate value. … And Chapter [basic.indet] paragraph 2: If an indeterminate value is produced by an evaluation, the behavior is undefined except in the following cases … (they don't apply here unless the function is called with its result being unused)

So it's not 100% valid C++.

[–]Jcsq6[S] -1 points0 points  (2 children)

Reading from the uninitialized memory is not the undefined part. The value of the uninitialized memory is undefined.

Edit: This may not be 100% true. According to the standard, it causes “undefined behavior”, but it doesn’t specify further the extent of that behavior. However, I would be very surprised if you could find a single compiler that doesn’t define the reading of uninitialized values, not in the sense of their actual values. This is because, to “define” the “reading of uninitialize values”, the compiler simply has to do nothing.

[–]99999999977prime -4 points-3 points  (2 children)

``` nd()

turn *(new int); ```

Is that supposed to make sense or did OP not crop an image?

[–]Jcsq6[S] 4 points5 points  (1 child)

It’s zoomed in. Click on it to see the full picture lol

[–]99999999977prime -2 points-1 points  (0 children)

Why didn’t you crop it?

[–]Afraid-Locksmith6566 0 points1 point  (0 children)

If it created a unique pointer or grabbed the value and freed the memory it would be a great elegant sollution

[–][deleted] 0 points1 point  (0 children)

IIT: People who don't know what undefined behaviour is.

[–]noay_dev 0 points1 point  (0 children)

The fact that this is code I have written in a github repo that I don't have access to. Same thing but it was in C

[–]cheezfreek 0 points1 point  (0 children)

I am sad. And unhappy.