On 04/10/2019 3:13 AM, IGotD- wrote:
According to the GC documentation this code snippet
char* p = new char[10];
char* q = p + 6; // ok
q = p + 11; // error: undefined behavior
q = p - 1; // error: undefined behavior
suggests that char *p is really a "fat pointer" with size information.
The pointer is raw.
There is no size information stored with it.
The GC will store size information separately from it so it can know
about reallocation and what its memory range is to search for.
However, if get some memory allocated by some C library that is
allocated with malloc we have no size information. We would get a char *
without any size information and according to the documentation we can
do anything including access out of bounds.
Access out of bounds is do-able with a pointer allocated by the GC.
int[] array;
arr.length = 5;
int* arrayPointer = array.ptr;
int value = arrayPointer[10]; // compiles!!! but will segfault at runtime
And of course that won't work in @safe code.
How does D internally know that a pointer was previously allocated by
the GC or malloc?
Either the GC has that information or it doesn't.
If we would replace the GC with reference counting. How would D be able
to distinguish a reference counted pointer from a raw pointer at compile
time in order to insert the code associated with the reference counting?
It can't.
This brings me back to MS managed C++ where they actually had two types
of "pointers" a managed pointer and the normal C++ pointers. Like this:
MyType^ instance = gcnew MyType();
In this case it was obvious what is done with GC and what wasn't (past
tense since managed C++ is deprecated). In this case it would be trivial
to replace the GC algorithm with whatever you want since the compiler
know the type at compile time.
There is only one type of pointer in D.
The GC is a library with language hooks. Nothing more than that.
It is easily swappable from within druntime.
But it does need to hook into threads and control them (e.g. thread
local storage and pausing them) so there are a few restrictions like it
must be chosen immediately after libc initialization at the start of
druntime initialization.