2

I was messing around with the memset function and did this:

int* p = malloc(sizeof(int);
memset(p, 0, 10000);

I was wondering why this is valid. I've only allocated 5 bytes of memory yet I can take up 10000 with memset. Why should I even malloc the memory if I can take up more than allocated? Could someone explain?

Serket
  • 3,785
  • 3
  • 14
  • 45
  • 3
    It is not valid -- it is undefined behavior. When you allocate 5-bytes -- you can only validly use 5-bytes. The fact it doesn't SegFault is undefined. It can appear to work correctly or crash --- or anything in between. `memset (p, 0, 5)` is all that is allowed in your case. In C, there is no need to cast the return of `malloc`, it is unnecessary. See: [Do I cast the result of malloc?](http://stackoverflow.com/q/605845/995714) – David C. Rankin Jul 10 '20 at 02:09
  • @DavidC.Rankin Haha I didn't even realise that that could cause problems. Thanks for the tip – Serket Jul 10 '20 at 02:11
  • Here is a good discussion about *undefined* and *implementation defined* behavior [Undefined, unspecified and implementation-defined behavior](https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior?r=SearchResults&s=1|277.0545) – David C. Rankin Jul 10 '20 at 02:13
  • 2
    Well, you can have 100 euros/dollars in your bank account and write a check for 500 euros/dollars. Doesn't mean that there isn't going to be a problem when someone goes to cash the check. Your call to memset is going to overwrite a bunch of memory. The check is going to bounce. Why would you even allocate 5 bytes for an integer? I haven't met a system that has 5 byte integers. – Joseph Willcoxson Jul 10 '20 at 02:14
  • @JosephWillcoxson it was a char pointer earlier but I changed it to an int to see if I was doing something wrong. Didn't even think about the size of an int. – Serket Jul 10 '20 at 02:15
  • 3
    The type of pointer only controls the *pointer-arithmetic* (e.g. `char *p` then `p+1` advances `sizeof(char)` (1-byte) to the next `char`, with `int *p`, `p + 1` advances `sizeof(int)` (generally 4-bytes) to the next `int`) Otherwise, a pointer is just a pointer -- which is why in C you can assign to/from `void*` without a cast. – David C. Rankin Jul 10 '20 at 02:18
  • 1
    @Serket -- Ever hear of buffer overrun security holes in software? Well, your code just demonstrated it. – PaulMcKenzie Jul 10 '20 at 04:17

2 Answers2

4

It's undefined behaviour, as in you can do it but the results are not defined, as in unpredictable, as in the program might crash.

In this case you can only write to the allocated region, or sizeof(int) * 5.

Why doesn't C prevent you from doing this? It's because the language design philosophy is that the programmer knows what they're doing and to not get in the way.

tadman
  • 208,517
  • 23
  • 234
  • 262
0

I was wondering why this is valid.

It isn't valid.

Why should I even malloc the memory if I can take up more than allocated? Could someone explain?

Because you can't.

You overflow the memory that you allocated. The behaviour of the program is undefined.

eerorika
  • 232,697
  • 12
  • 197
  • 326