0

Here is a code I wrote for GCC compiler.

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int *p;
    p = (int *)malloc(9 * sizeof(char));
    p[0] = 2147483647;
    p[1] = 2147483647;
    p[2] = 1025;
    printf("%d, %d, %d, %d\n", sizeof(char), *(p), *(p+1), *(p+2));
}

The output is as follows:

1, 2147483647, 2147483647, 1025

My question is, though I allocated only 9 bytes to the pointer, It seems to use all the 12 bytes. The result is same (barring a compiler warning), if I cast (char *) instead of (int *). Does the allocation of malloc() is full circle? i.e it always allocate in multiples of Data Type of the pointer,irrespective of what we allocated? or is it implementation specific?

sokkyoku
  • 2,161
  • 1
  • 20
  • 22
Umesh C G
  • 45
  • 5

4 Answers4

7
    p = (int *)malloc(9 * sizeof(char));

What you are doing is undefined behavior if size of integer is 4 bytes. Because you allocated 9 bytes and used 12.

Casting doesn't have any effect, actually you shouldn't cast result of malloc in C at all.

Another place where you triggered undefined behavior is using the wrong format specifier for sizeof, you should use %zu instead of %d in printf (for sizeof).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Giorgi Moniava
  • 27,046
  • 9
  • 53
  • 90
3

As others have mentioned, you are writing past the end of a malloced buffer. This invokes undefined behavior.

What undefined behavior means is that anything can happen. The program may crash, it may give unexpected results, or (in this case) it appears to work correctly.

Making a seemingly unrelated code change could make your program suddenly start crashing.

To illustrate what is happening, here is the output from running your program under valgrind :

[dbush] valgrind /tmp/x1
==19430== Memcheck, a memory error detector
==19430== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==19430== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==19430== Command: /tmp/x1
==19430==
==19430== Invalid write of size 4
==19430==    at 0x40050E: main (x1.c:11)
==19430==  Address 0x4c18048 is 8 bytes inside a block of size 9 alloc'd
==19430==    at 0x4A0610C: malloc (vg_replace_malloc.c:195)
==19430==    by 0x4004E9: main (x1.c:8)
==19430==
==19430== Invalid read of size 4
==19430==    at 0x40051C: main (x1.c:12)
==19430==  Address 0x4c18048 is 8 bytes inside a block of size 9 alloc'd
==19430==    at 0x4A0610C: malloc (vg_replace_malloc.c:195)
==19430==    by 0x4004E9: main (x1.c:8)
==19430==
1, 2147483647, 2147483647, 1025
==19430==
==19430== HEAP SUMMARY:
==19430==     in use at exit: 9 bytes in 1 blocks
==19430==   total heap usage: 1 allocs, 0 frees, 9 bytes allocated
==19430==
==19430== LEAK SUMMARY:
==19430==    definitely lost: 9 bytes in 1 blocks
==19430==    indirectly lost: 0 bytes in 0 blocks
==19430==      possibly lost: 0 bytes in 0 blocks
==19430==    still reachable: 0 bytes in 0 blocks
==19430==         suppressed: 0 bytes in 0 blocks
==19430== Rerun with --leak-check=full to see details of leaked memory
==19430==
==19430== For counts of detected and suppressed errors, rerun with: -v
==19430== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 4 from 4)

You can see from this output that you are reading and writing past the end of your allocated buffer.

dbush
  • 205,898
  • 23
  • 218
  • 273
1

The fact that you were able to write to the "extra" bytes does not mean that they were allocated to you; it just means that they exist. You have no reason to expect that those bytes will not "magically" change in the future, since you didn't allocate them, and if some other code did, could change them (and, unlike your code, do so legitimately).

Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
1

In C, pointers can go to any memory they want. In your code, you have allocated only 9 bytes. As C language does not offer bound checking, you can simply move your pointer to any location. But, it does not mean that you have the control over those memory locations. It can result in sigsegv, application crash or AccessViolationException (if this code is used natively by some other language like C# or Java). Also, these bytes can be modified by some other program that can corrupt your data.

Amber Beriwal
  • 1,568
  • 16
  • 30