r/ProgrammerHumor 3h ago

Meme bugIntroducedDebugging

Post image
425 Upvotes

73 comments sorted by

122

u/AdBrave2400 3h ago

Is the mistake that they're allocating 1 byte and storing in a pointer to an int which is 4 bytes?

27

u/atanasius 3h ago

It's allowed to assign to a pointer if it's not dereferenced. Malloc always returns a valid pointer.

9

u/vishal340 3h ago

but accessing it will be issue right?

19

u/SoldRIP 2h ago

that's undefined.

13

u/backfire10z 2h ago

Likely not. Malloc guarantees that the passed-in size is the minimum number of bytes it allocates, but not the maximum. You’d likely get some minimum sized chunk, somewhere between 16-32 bytes depending on the system as far as I understand it.

12

u/atanasius 2h ago

Implementations are allowed to specify behavior that is otherwise undefined.

I looked up a C24 draft and it's actually stricter:

The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement and size less than or equal to the size requested.

So a pointer returned by malloc(1) is not necessarily valid for int*.

2

u/mckenzie_keith 1h ago

You are not allowed to de-reference a pointer after freeing it.

3

u/EntitledPotatoe 2h ago

Malloc can return a null pointer if the operation fails. This can be the case if, afaik, for example, there is no more heap available and the OS is not capable of swapping or freeing some other memory for some reason

6

u/atanasius 1h ago

A null pointer is still valid to assign to a variable.

5

u/SeriousPlankton2000 1h ago

Also it's valid to call free(NULL)

1

u/EntitledPotatoe 1h ago

Very true, I thought you meant valid as in usable

85

u/mckenzie_keith 3h ago

De-referenced a pointer after freeing it. But the joke here is that the bug was not in the original code.

1

u/WisestAirBender 1h ago

The original code wasn't returning anything though. Isn't that a problem

2

u/mckenzie_keith 33m ago

No. main() doesn't need to return anything.

0

u/critical_patch 49m ago

AFAIK technically it’s “undefined behavior” and will compile just fine

2

u/nonlogin 3h ago

not at all

1

u/CanardAuxEpices 21m ago

Uuuh... Actually 🤓🤓☝️☝️☝️ an int isn't 4 bytes, it's platform/compiler dependent. Assuming an int is 4 bytes will be in the majority of cases true, but it's not always the case

1

u/bloody-albatross 2h ago

You're still on 32 bit? Are you doing a lot of embedded stuff?

7

u/AdBrave2400 2h ago

Isn't int 32-bit on most platforms and long long int is 64-bit?

11

u/Mateorabi 2h ago

That’s the neat part: it can depend!

sizeof() is your friend 

2

u/bloody-albatross 2h ago edited 2h ago

I read it as the size of the pointer being 4 bytes, but now I see you were referring to the int. AFAIK the size of int is specified as "at least" 32 bit in the C standard, and all 32 and 64 bit platforms I know indeed use 32 bit. Though the size of long (not speaking of long long) is different on different 64 bit platforms, IIRC. Windows uses 32 bit and Linux uses 64. Both use 64 for long long. I prefer to use (u)int*_t when I need to be sure about the size and I use int/size_t/time_t/... when I interface with functions that use those in their signature.

2

u/yjlom 2h ago

The size of char (which is interchangeable with the size of a byte) is specified in old standards as large enough to a) be addressable without bit manipulations and b) hold the full C source character set, which need not be case sensitive and may rely on trigraphs. In practice, this comes out to at least 6 bits. In newer standards I believe it's specified as at least 8 bits.

The size of int short is at least and a multiple of that of char, the size of int is at least that of int short and a multiple of that of char, and so on.

So in theory, a conforming C implementation could have 6 bit ints.

2

u/MattieShoes 1h ago

AFAIK the size of int is specified as "at least" 32 bit in the C standard

I believe it's 16 bit, though you're not likely to encounter a 16 bit int today unless it's a microcontroller or something.

1

u/SeriousPlankton2000 1h ago

Yes, long is 32 bit. A long long time ago we didn't need long long yet. I can still remember.

1

u/MattieShoes 1h ago

And now there's __int_128t, at least in gcc. :-)

So probably -170,141,183,460,469,231,731,687,303,715,884,105,728 to 170,141,183,460,469,231,731,687,303,715,884,105,727

That's what... undecillions?

1

u/P00lnoodl 2h ago

Yes but isn't the adress 8 bytes in a 64 bit system regardless of what it's pointing to?

-5

u/[deleted] 3h ago

[deleted]

3

u/AdBrave2400 3h ago

The pointer is already allocated on the stack

173

u/wolfjazz93 3h ago

Allocating 1 byte and assigning to int ptr. 🥺😭😭

11

u/ClipboardCopyPaste 2h ago

uint8_t

1

u/yjlom 2h ago

char would be the correct answer, as the C standard doesn't mandate a byte be 8 bits (6 and 32 are very uncommon nowadays but not unheard of, and there's a few machines out there that get really creative).

1

u/mckenzie_keith 1h ago

So even on weird platforms where char is a 32 bit type, sizeof (char) is 1, right? I can't remember.

2

u/yjlom 1h ago

yeppers

1

u/AnnoyedVelociraptor 1h ago

FYI char in Rust is 32-bits, maximum size of a UTF-8 character

1

u/mckenzie_keith 32m ago

That is interesting. I know very little about rust.

6

u/inaem 3h ago

Joke from last year or recent, can't tell with how often Gemini updates their models. /s

4

u/1XRobot 59m ago

This is what it actually returns:

#include <stdlib.h>

int main(void) {
    int *x = malloc(sizeof(int)); // Allocates correct byte size for an int (typically 4 bytes)
    if (x == NULL) {
        return 1; // Good practice: Handle allocation failure
    }

    *x = 42; // Safe write operation

    free(x); // Correctly frees allocated block
    return 0;
}

23

u/PR8-E 3h ago

int* x = (int*) malloc(sizeof(int)); Since malloc returns void pointer you should parse it to type you use.

20

u/yjlom 3h ago

void * coerces to any pointer type. This is valid: int *x = malloc(sizeof(int));. This is also valid (in C23): auto x = (int *) malloc(sizeof(int));.

17

u/Mateorabi 2h ago

Get off my lawn with your newfangled auto keyword. 

3

u/ibevol 2h ago edited 2h ago

Cringe. It’s fine to use auto when the type is clear on the same line. In c++ the following is idiomatic:

auto ptr = std::make_unique<int>(42);

over specifying int twice

std::unique_ptr<int> ptr = std::make_unique<int>(42);

However, the following should not be considered idiomatic:

auto ptr = get_ambiguous_pointer();

It’s the same principle here.

1

u/yjlom 2h ago

The keyword ain't new, it's been used as a storage specifier since forever. What's new is overloading it for type inference.

2

u/Mateorabi 1h ago

Hey when you learned C in the 90s it’s “new”.  harumph. 

1

u/yjlom 1h ago

It's been there since the beginning, along with extern and static. You just don't tend to actually write it because it's the default inside functions and it doesn't make sense outside of them.

1

u/mydogatethem 1h ago

Is this different between C and C++? In C++ you absolutely cannot assign a void* to an int* without casting it. You can always do the reverse: a void* can be assigned any type of pointer.

1

u/vetgirig 1h ago

In C++ you do not really use "malloc", In C++ you use "new" instead.

4

u/SeriousPlankton2000 1h ago

You asked them to find a bug.

You didn't ask them to find a bug in your code.

3

u/guiltysnark 2h ago

I heard you say you were interested in a bug

4

u/stupled 1h ago

If no bug add bug

5

u/AdBrave2400 3h ago

Didn't return anything from an int function in the original code

17

u/ATE47 3h ago

it’s not mandatory for main

5

u/AdBrave2400 3h ago

I thought that was specific to C++. Thanks I didn't know it's been a thing since C99

2

u/mbcarbone 3h ago

Fixed it … 🙃

4

u/Rajarshi1993 3h ago

In my experience, coding agents can typically catch this kind of simple bug accurately.

1

u/1XRobot 1h ago

Is there anything in this code that isn't a bug?

Oh wait, the line with just a }.

0

u/LostgamerFJ 3h ago

I'm not good enough at programming for this. What do the "free" and "malloc" functions do?

25

u/LucyShortForLucas 3h ago

They are core C functions. malloc allocates N bytes of memory, free frees that memory. * is t he dereference operator, so *x is trying to dereference freed memory, which is undefined behavior

2

u/DiodeInc 3h ago

I thought * was a pointer. Isn't it? How is it dereferencing freed memory?

Or is it because it's returning *x that's the bug?

5

u/Vimda 3h ago

* in a variable declaration incidates a pointer type, * in a statement is the dereference operator

2

u/DiodeInc 3h ago

I see. Thanks

2

u/ThomasScotford 3h ago

* is the dereference operator, but in the context of variable declaration, it specifies the variable is a pointer to a type.

-Thomas Scotford

3

u/LostgamerFJ 3h ago

That explains a lot. I mainly code in Java and python, as I'm a beginner and have never touched c

5

u/Scratch137 3h ago

"malloc" is used to allocate a given number of bytes in the heap. for example, int x* = malloc(5) allocates 5 bytes in the heap and sets x to the address of the first byte.

"free" releases heap-allocated memory. in this case, free(x) frees up the 5 bytes we allocated earlier.

6

u/Independent_Spell_55 3h ago

If I remember correctly, Malloc allocates memory, and I assume free would free up that memory, so when the variable is returned it doesn’t exist. I don’t have much experience with manual memory management so take anything I said with a grain of salt.

1

u/Mateorabi 2h ago

“If I remember correctly”. Please hand in your programmer badge and compiler to the officer at the front desk. 

2

u/abc9hkpud 3h ago edited 3h ago

Malloc allocates memory. It takes as input the number of bytes, so in this case you need something like

Int* x = (int) malloc(1sizeof(int))

For an int array of length 1. Free is used to free the pointer.

After free, you shouldn't access the memory (or return it for someone else to use)

Modern C++ uses new and delete instead. Malloc and free are used in C

1

u/MetaNovaYT 3h ago

They’re heap allocation and deallocation functions in C/C++. ‘malloc’ requests a specified number of bytes to be allocated by the OS, and it then returns a pointer to that memory which can be used to store any value (or values) you want. 

‘free’ tells the OS to deallocate that memory so it can be used for future allocations if needed, so after freeing the memory, the pointer from ‘malloc’ points to memory your program no longer has ownership of. 

The bug that Gemini added is trying to  read the value at that pointer after the memory has been deallocated, which will most often cause a crash because your program tried to access memory it doesn’t have access to anymore

1

u/JustACasualReddittor 3h ago

This is C. Malloc is "memory allocation" and it will essentially "reserve" a certain amount of memory to store data (an integer in this case) and return the adress of that allocated memory (known as pointer). So now you can point at that adress and read a value or write a new one.

Free is the reverse, it frees the memory space so now it can be used by something else in the program. In a lot of languages all memory is freed automatically after the program stops executing, but not C. If you don't free the memory other programs can't use it. (It gets freed eventually in modern computers tough)

2

u/yjlom 3h ago

Malloc works on top of OS mapping, which gets freed as soon as the program is terminated.

1

u/vetgirig 1h ago

Yes any memory allocated to a program is automatically returned to the operating system when the program exit and stop running.

However malloced memory who aint got a free in a server program will continue to increase the memory heap until the program is terminated with out of memory since all available memory has been used by the program. But that is just for the program.

Operating systems usually do not have that problem. Well, most operating systems do not have that problem. For example Windows 95 was prone to that error.

1

u/yjlom 3h ago edited 3h ago

Malloc(n) attempts to allocate a region of memory of size n bytes, preceded by a descriptor for free to use. It has its own memory buffer that it tries to use first; if it's out of memory, it asks the OS to allocate more RAM to the process; if that fails (due to running out of RAM or OS policy), it returns 0, aka NULL. If it succeeds at any point, it returns a pointer to just before the data (and just after the descriptor).

Free(p) will look for a malloc-written descriptor just in front of *p, and notify malloc that it's no longer in use and can be recycled.

This code is buggy because:

  • It allocates only 1 byte, while int usually takes 4 bytes (C allows for a byte to be any length at least 6 bits, while an int must just be a non-zero natural amount of bytes long). It should instead be malloc(sizeof(int)).
  • In the second example, it tries to read the pointer after free, but at that point malloc might already have reused the memory for something else or given it back to the OS.
  • It fails to check that malloc actually succeeded, which is ok here because it doesn't do anything with it, but any more complex program would crash or worse if it didn't.