I am allocating memory for an array, but I am moving where the pointer points forward a little. Accessing the elements works fine. It started to produce a problem with freeing the allocated memory though. Malloc complains that the pointer being freed was never allocated. The problem can reproduced with this simplified code:
int *pointer = malloc(sizeof(int)) + 1;
free(pointer - 1);
I started experimenting, and found this slight variation of the code to work.
int *pointer = malloc(sizeof(int));
pointer += 1;
free(pointer - 1);
What is the += doing different than just adding 1 to the pointer malloc returns in one line?
Pointers contain addresses. Adding two addresses makes no sense because there is no idea what it would point to. Subtracting two addresses lets you compute the offset between the two addresses.
You can only add or subtract integers to pointers. When you add (or subtract) an integer (say n) to a pointer, you are not actually adding (or subtracting) n bytes to the pointer value. You are actually adding (or subtracting) n-times the size of the data type of the variable being pointed bytes.
Pointer arithmetic and arrays. Add an integer to a pointer or subtract an integer from a pointer. The effect of p+n where p is a pointer and n is an integer is to compute the address equal to p plus n times the size of whatever p points to (this is why int * pointers and char * pointers aren't the same).
Adding two pointers is illegal in c program but pointer and integer addition is legal. subtraction of two pointers is also legal. multiplication & division of two pointers are also illegal.
The return type of malloc
is void *
, which, according to the standard, cannot be used for pointer arithmetic.
There is a GNU extension, however, that treats sizeof(void)
as 1
and that is why your first fragment compiles. Later on, pointer - 1
subtracts sizeof(int)
and not 1
, hence the pointer mismatch.
The actual offsets applied when doing pointer arithmetic always depend on the type of the pointer. Since pointer
is an int *
, the actual offsets will be multiplied by sizeof(int)
. If sizeof(void)
is 1
or if it's a char *
pointer (sizeof(char) == 1
), no multiplication takes place.
Pointer arithmetic can be done using either of +
or +=
. It has nothing to do with the error produced.
malloc
returns void *
type. C standard says that:
The
void
type comprises an empty set of values; it is an incomplete type that cannot be completed.
For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to a complete object type and the other shall have integer type. (Incrementing is equivalent to adding 1.)
void *
is pointer to incomplete type. Therefore, no addition will be performed with void *
type. That's why
int *pointer = malloc(sizeof(int)) + 1;
is wrong and will lead to run time error on executing free(pointer - 1);
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With