Your program has undefined behavior as you access memory that hasn't been allocated to your program.
Looking at some details:
int *a = malloc(sizeof(int));
// This part is fine. It will try to allocate the amount of memory
// needed for storing exactly 1 int. It will assign the pointer a with
// with a value that points to the allocated memory.
However, the malloc
may fail (i.e. be unable to allocate the amount of memory needed) so you must check whether it failed. If malloc
fails it will return NULL. So you need to add:
if (a == NULL)
{
// malloc failed...
// print error
exit(1);
}
Next line is:
printf("%d %d %d\n", *a, *(a + 1), *(a + 2));
// This is undefined behavior:
// *a will read the value of the memory just malloc'ed as an int
// In principle that is OK but since you didn't initialize the
// memory, it is still undefined behavior
//
// *(a+1) and *(a+2) will read memory after the memory malloc'ed
// So you access memory not allocated to you. That is undefined
// behavior
So what you should do is to 1) initialize the memory first and 2) only access memory allocated to you. Like:
*a = 42;
printf("%d\n", *a);
The next line:
a = realloc(a, sizeof(int) * 2);
// In principle this is valid. However, it is not good as realloc may
// fail just like malloc.
So you should do:
int* temp = realloc(a, sizeof(int) * 2);
if (temp == NULL)
{
// Error handling or just exit...
free(a);
exit(1);
}
a = temp;
For the rest of the code you have problems similar to the ones mentioned above.
But I initialised *(a + 2) to 16 while as you can see I only allocated ~8 bytes not more (it needs at least 12 bytes). How is this possible?
The C language doesn't check that everything you do is valid. In other words - C let you do what you ask for. It is your own responsibility to make sure that you only do valid things.
At run time the system may detect that the program is doing illegal things. If so a crash (core dump) will happen.
However, there are many situations where the system can't detect that your program is doing something illegal. So the program will just carry on. That can result in all kinds of strange errors but it may also look as if the program is correct the first 100 times you execute it and then fail the next time. That is what undefined behavior is.... undefined - you'll never know what may happen.
So coding in C puts a lot of burden on you. It is very easy to do illegal things in C. It is your responsibility to make sure that you only do legal things.
Today a number of tools are available for analyzing C and finding wrong code, e.g. valgrind and coverity.