so I'm trying to write my own 'malloc' library and I am having problems with my global variables.
In the code below you can see, that I'm creating an int pointer to write an integer into the char-array, and that int pointer points to the first byte of my char-array, thinking it's memory for an integer.
char myMemory[1048576];
int* pMem = (int*)(&myMemory[0]);
*pMem = (1048576-5);
myMemory[4] = 'f';
//... and so forth
For the last line I get the following error message:
redefinition of 'myMemory' with a different type 'int [4]' vs 'char [1048576]'
For *pMem = (...); I get the following
invalid operands to binary expression 'int*' and 'int*'
maybe I'm not allowed to change global variables globally, when I did the same stuff in a testing function everything worked.
It's been impossible for me to find that out on the internet, because everybody is asking how to change global variables in functions which is..
I hope someone can help me with this, because I think otherwise I will soon burn my house. Thank you in advance.
Tim
Quick Summary:
That error really doesn't apply to what you're trying to do - implement malloc()
.
Fix
Use a compiler or compiler argument that doesn't give you the redefinition of 'myMemory' with a different type 'int [4]' vs 'char [1048576]'
error.
Full Answer
Strictly speaking, this code
int* pMem = (int*)(&myMemory[0]);
is a strict aliasing violation and potentially violates 6.3.2.3 Pointers, p7 of the C standard:
A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined.
Your error
redefinition of 'myMemory' with a different type 'int [4]' vs 'char [1048576]'
is because you violated the strict aliasing rule.
In general, in C you can not take memory that didn't start as having a specific type and treat it as having another type - with the exception that you can always treat any memory as char
type. You can't take a char
array and treat it as an int
array, for example.
That's the strict aliasing rule.
But you can take an int
array and treat is as a char
array - or signed char
or unsigned char
array.
And even if the memory did somehow start as an int
but all you have is a char
pointer (or void
pointer) to it, when you cast it back and access it as an int
, the memory has to be properly aligned for the platform you're on.
Your code may or may not do that - you won't know for sure until you actually run it. If it doesn't meed alignment requirements, you might get a SIGBUS
or some other failure - like this.
Breaking any of those rules results in undefined behavior.
BUT
In this case you're "trying to write [your] own 'malloc' library", and malloc()
is provided by the implementation, so those rules don't really apply as you're providing a part of the C implementation itself.
Why? Why don't those rules apply to the implementation of the C environment itself?
They can't, because of 7.22.3 Memory management functions:
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 then used to access such an object or an array of such objects in the space allocated
You simply can not do that in strictly-conforming C code.
Memory managed by malloc()
(and calloc()
and ...) starts as "untyped", but you can't have such "untyped" memory in conformant C code. What about using void *
to reference the memory? You can't do pointer arithmetic on void *
pointers in conformant C code. And you're going to have to do pointer arithmetic to manage the memory. So you pretty much have to use pointers to some type to manage the memory.
And you can't use arrays to avoid such pointer arithmetic, because those arrays also have to have a concrete type.
So you have to "type" the memory you manage in your malloc()
implementation, yet when that memory gets passed to a caller as the result of a malloc()
call, the strict aliasing rule gets violated.
If you manage your memory right, your malloc()
implemenation won't violate the alignment restrictions of 6.3.2.3 Pointers, p7.
Why does so much code break these rules?
Because the x86 platform most people writing code use is EXTREMELY FORGIVING on misaligned accesses.