OT: Dynamic-CC, GC, Dynamic Types, and Prototype OO in C

C

cr88192

Blake McBride said:
I added OO capabilities to C including a full MOP, multiple inheritance,
threads, and GC. It is very highly portable to Linux, Windows, Mac, etc.
I call it Dynace and it is open source. See:

http://blake.mcbride.name

anything interesting to say about it?...

ok, it is a preprocessor, and my effort is a full compiler.

I implemented said prototype OO system (pure library feature), but haven't
had much reason to use it yet.
some of the other facilities, have been used in a minor effort of starting a
rewrite of the compiler frontend.

basically, I am going from using one GC/dynamic-typesystem (a precise
system, using tagged references, and a S-Expression based representation for
ASTs and other data), to the new system (the one specified before, but now
with more facilities).

internally, I am going over to using a DOM-like representation for the ASTs
and other internal compiler data (back in 2004/2005, I had been using a VM
of mine, which had also used XML-based ASTs).

of course, all this requires a not exaclty minor level of rewriting for the
compiler frontend...


more recently, another issue has come up:
that of concurrency-related features.

what I am now currently considering, is implementing a library based
message-passing API, and possibly an "abstract" shared memory API.

the shared memory API would be handle-based, and be API-call driven, mostly
in the name of making it "generic", aka: can be implemented purely with
sockets and possibly buffering, and not necessarily involve OS-specific
mmap-like features (mmap on linux, VirtualAlloc on windows). of course, I
could allow such features (getting "pointers" to shared objects), but who
knows (handles would probably be good enough, and such mapping makes
consistency/caching a little more complicated).

another possibility is that of a "shared object system". in such a system,
the fact that objects are shared could be largely hidden mostly by making
them look and behave mostly like local objects (this would be a lot more
complicated, for various reasons, than either a direct or indirect
shared-memory system).

objects would be shared, but nearly everything else would be copied
(problems are made, however, with a conservative GC and an open-ended
typesystem, as this would only really work well for types which can be
handled precisely).

or such...
 
P

Phil Carmody

Those requirements aren't very "conservative".

I believe that it is impossible to implement garbage collection in C
which meets the design requirements:

(1) Makes no demands beyond Standard C of where you can store pointers
that reference potentially garbage-collected memory.
(2) *NEVER* collects memory that is actually referenced.
(3) At least occasionally collects some garbage.
(4) Operates without disastrous effect on performance (which I'll
arbitrarily define as slowing down the program by a factor of one
million or more).
(5) garbage-collected memory allocation is done by calling malloc()


A true "conservative" garbage collector will detect references to
potentially garbage-collectable memory in all of the following
places:

(1) local variables
(2) local register variables
(3) global variables
(4) structures in malloc()ed memory.

(4.5) And not just with the architecturally expected alignment.
The pointer values could have been memcpy'd to arbitrary
locations, so all byte alignments are possible.
(5) structures in (possibly multi-terabyte) files
(6) pointers turned into strings with sprintf(..., "%p", ...)
and later turned back into a pointer.
(7) pointers stored in encrypted form

(5) is an enormous performance-killer.
(7) makes it nearly impossible to prove that a reference ISN'T a
reference to any particular block of memory.

It probably solves the halting problem in the process.
On the other hand, garbage collection routines can violate the C
standard (garbage-collection routine writers are generally unwilling
to admit that these violate the C standard, but they do) and still
be of practical use, by freeing memory that is referenced outside
of memory (drop requirement (5)), and not in the form of a pointer
(drop requirements (6) and (7)).

I think (5), (6), and (7) are justifiable. I haven't made
my mind up about my (4.5) yet.

Phil
 
C

cr88192

Phil Carmody said:
(4.5) And not just with the architecturally expected alignment.
The pointer values could have been memcpy'd to arbitrary
locations, so all byte alignments are possible.


It probably solves the halting problem in the process.


I think (5), (6), and (7) are justifiable. I haven't made
my mind up about my (4.5) yet.

by traditional definitions, one does not need "magic" for it to be a
conservative GC, one just needs to be able to use it without too much hassle
(and not have to worry about stuff like registering or unregistering roots,
always getting/setting values via special accessors, ...).

pointers in files, unaligned memory, obfuscated pointers, ... are not really
problems in practice (since, hell, these things don't normally work so well
anyways, nor are they really required to work in the first place...).

malloc'ed memory is an issue, usually requiring a disclaimer like "warning:
do not mix with malloc..." (otherwise, this would require 'virtualizing' the
runtime, ...).

as noted, it does require, in effect, providing runtime wrappers for a lot
of things, such as:
memory allocation and freeing;
thread creation and thread-local-storage;
....

as well as the issue that (in my case), I have never implemented a proper
write barrier, so to be properly safe requires using a software write
barrier (a function wrapped by a macro), which I have been consistently too
lazy to do all the time...

I guess the result is that I have a GC which works, most of the time, but
may still screw up and cause crashes sometimes...


as well as the consistently annoying issue:
a conservative GC is just never as fast or as memory-tight as a precise GC;
but OTOH, precise GCs are just so much of a hassle to use that I rarely do
so for all that long (or on that large of a scale), and once the propspect
of mixing multithreading and precise GC comes up (in the context of C),
making it all "safe" quickly becomes, IMO, unacceptably painful...

sadly, in some places I have ended up doing custom non-GC memory management,
mostly so that I can do tasks which produce lots of garbage, and then simply
"flush" the whole local heap when done, rather than have to deal with the
GC's panic at the sudden creation of 10s of MB of garbage in a short time,
as can happen whenever compiling C source files, ... (my GC is best behaved
when being treated mostly as a manual MM...).

I have thought of ideas before as to how to address these issues (such as
adding support for local virtual heaps, changes to the GC's allocation
strategy, ...), but as of yet have not gotten to this... (actually, the
present GC is more than a little of a hacky mess... as making it
multithreaded, later carving it into several libraries, ... were all not
exactly done so cleanly, ...).


of course, in the conservative case, at least C++ could help some with the
convinience by allowing operator overloading to assist with some tasks (such
as the SW write barriers), but for other more pressing reasons, I continue
to use mostly plain C (for both the implementation and scripts, or at least
all of which is not in assembler...).

I hope at least to eventually have C# and Java up and running on this as
well...
 
K

Keith Thompson

cr88192 said:
pointers in files, unaligned memory, obfuscated pointers, ... are
not really problems in practice (since, hell, these things don't
normally work so well anyways, nor are they really required to work
in the first place...).
[...]

Yes, they really are required to work in the first place. If I treat
the contents of a pointer object as an array of unsigned char,
scramble the bytes so there's no copy of the pointer value anywhere in
memory, and then restore the original pointer representation (and
therefore the original value), then the restored pointer must still be
valid in a conforming C implementation. If something goes behind my
program's back and deallocates a chunk of memory because it doesn't
recognize that I'm still using it, that's a violation of C
conformance.

On the other hand, the convenience of GC might be worth the loss of C
standard conformance in some corner cases. But it's still something
that anyone implementing or using GC should be aware of.
 
J

James Kuyper

cr88192 said:
....
pointers in files, unaligned memory, obfuscated pointers, ... are not
... really required to work in the first place...).

As far as I understand it, the C standard does indeed require all three
of those techniques to work, at least if they're used properly. It says
that the value represented by an object is determined by it's object
representation. All three of the methods you describe are ways in which
a given object representation can disappear from all properly aligned
memory, and then be restored to properly aligned memory. If the object
in question is a pointer object, such processes cause the recovered
pointer object to represent the same value that was represented by the
original pointer value, unless something has happened in the meantime
that permits the pointer's value to have become invalid. It would have
to be something that would have been equally disastrous if the the
object representation had never disappeared.

Can you cite any text from the standard that gives any one of those
techniques (if used properly) to fail? Another way to put that is, can
you cite any text the presents an unavoidable barrier to using one of
those techniques? "used properly" means nothing more or less than
avoiding the avoidable barriers.
 
C

cr88192

James Kuyper said:
As far as I understand it, the C standard does indeed require all three of
those techniques to work, at least if they're used properly. It says that
the value represented by an object is determined by it's object
representation. All three of the methods you describe are ways in which a
given object representation can disappear from all properly aligned
memory, and then be restored to properly aligned memory. If the object in
question is a pointer object, such processes cause the recovered pointer
object to represent the same value that was represented by the original
pointer value, unless something has happened in the meantime that permits
the pointer's value to have become invalid. It would have to be something
that would have been equally disastrous if the the object representation
had never disappeared.

Can you cite any text from the standard that gives any one of those
techniques (if used properly) to fail? Another way to put that is, can
you cite any text the presents an unavoidable barrier to using one of
those techniques? "used properly" means nothing more or less than
avoiding the avoidable barriers.

the standards don't say they are allowed to fail, I just don't know of
anywhere where they are required, as such, to work...

one can debate that, although they can destructure and restructure a
pointer, it says little about whatever is referenced "by" this pointer. so,
they recreate the pointer, but what is to say that the memory at this
address is required to still be valid?...

this is much the same as saying that crafting a pointer to an arbitrary area
of memory is required to work. yes, one can craft the pointer, but no, it is
not required to actually point at whatever was intended (or that it be
addressable).


what is to say that the app still has the same address-space layout as when
the pointer went out of visibilty?...


but, whatever the case, some things seem "reasonable", and others less so.

what can be done in what ways invariably will depend on the specifics of the
architecture:
some archs may use flat and others segmented memory;
some may have tagged and others untagged pointer representations;
some may allow unaligned memory objects and others will not.

some restrictions may well be resonable (no serialized, misaligned, or
obfuscated pointers, ...).
 
E

Eric Sosman

Keith said:
cr88192 said:
pointers in files, unaligned memory, obfuscated pointers, ... are
not really problems in practice (since, hell, these things don't
normally work so well anyways, nor are they really required to work
in the first place...).
[...]

Yes, they really are required to work in the first place. If I treat
the contents of a pointer object as an array of unsigned char,
scramble the bytes so there's no copy of the pointer value anywhere in
memory, and then restore the original pointer representation (and
therefore the original value), then the restored pointer must still be
valid in a conforming C implementation. If something goes behind my
program's back and deallocates a chunk of memory because it doesn't
recognize that I'm still using it, that's a violation of C
conformance.

On the other hand, the convenience of GC might be worth the loss of C
standard conformance in some corner cases. But it's still something
that anyone implementing or using GC should be aware of.

As a concrete example of a "non-exotic" situation in which
a pointer might be mangled and then reconstituted, consider using
qsort() on an array of structs that contain pointers. Somewhere
in the process of sorting, qsort() must exchange the contents of
array slot [X] with array slot [Y], and must do so in a type-
blind fashion. A perfectly reasonable qsort() implementation
might perform the exchange by repeated copies through a buffer
smaller than the struct, or by means of the XOR trick. Either
of these could mangle the struct contents -- pointer included --
while the exchange was in progress, although (of course) the
mangling would be de-mangled by the time the exchange was over.

It's unlikely that a (single-threaded) program would perform
a GC while qsort() was in mid-mangle, but the mangling certainly
could occur as part of a perfectly innocuous operation.
 
C

cr88192

Eric Sosman said:
Keith said:
cr88192 said:
pointers in files, unaligned memory, obfuscated pointers, ... are
not really problems in practice (since, hell, these things don't
normally work so well anyways, nor are they really required to work
in the first place...).
[...]

Yes, they really are required to work in the first place. If I treat
the contents of a pointer object as an array of unsigned char,
scramble the bytes so there's no copy of the pointer value anywhere in
memory, and then restore the original pointer representation (and
therefore the original value), then the restored pointer must still be
valid in a conforming C implementation. If something goes behind my
program's back and deallocates a chunk of memory because it doesn't
recognize that I'm still using it, that's a violation of C
conformance.

On the other hand, the convenience of GC might be worth the loss of C
standard conformance in some corner cases. But it's still something
that anyone implementing or using GC should be aware of.

As a concrete example of a "non-exotic" situation in which
a pointer might be mangled and then reconstituted, consider using
qsort() on an array of structs that contain pointers. Somewhere
in the process of sorting, qsort() must exchange the contents of
array slot [X] with array slot [Y], and must do so in a type-
blind fashion. A perfectly reasonable qsort() implementation
might perform the exchange by repeated copies through a buffer
smaller than the struct, or by means of the XOR trick. Either
of these could mangle the struct contents -- pointer included --
while the exchange was in progress, although (of course) the
mangling would be de-mangled by the time the exchange was over.

It's unlikely that a (single-threaded) program would perform
a GC while qsort() was in mid-mangle, but the mangling certainly
could occur as part of a perfectly innocuous operation.

yes, good points...

however, we can also assume that a qsort implementation would not be
implemented in a way which is unsafe for the architecture in question...

on x86, this could mean though that a pointer could take a trip through a
register (xor swap is unlikely for GPRs on x86 due to 'xchg', but could be
reasonable with XMM regs, which are sometimes used as a convinient and
reasonably efficient way to move chunks of memory around, especially if
properly aligned, and although xor is less likely on XMM regs due to their
typically lower register pressure...).

but, whatever the case, a pointer traveling through an XMM reg could
potentially momentarily disappear from visibility.

as noted though, in these cases it is unlikely that the pointer would remain
out of sight long enough for the GC to miss it (vs. what would likely occur
with things like pointer obfuscation and similar...).

 
K

Keith Thompson

cr88192 said:
the standards don't say they are allowed to fail, I just don't know of
anywhere where they are required, as such, to work...

Well, I do.
one can debate that, although they can destructure and restructure a
pointer, it says little about whatever is referenced "by" this pointer. so,
they recreate the pointer, but what is to say that the memory at this
address is required to still be valid?...

Let's take a (somewhat) concrete example, with a bit of pseudo-code
and ignoring error handling to keep things simple.

#include <whatever is needed>
int main(void)
{
int *p = malloc(sizeof *p);
/* Assume p != NULL */
*p = 42;
/* We've just allocated an object and assigned a value to it. */
MANGLE(p);
/* Now there's no existing pointer to the object. */
UNMANGLE(p);
/* Now we've restored the representation, and therefore the value,
* of p */
printf("%d\n", *p);
/* The above had better print "42". */
free(p);
return 0;
}

You are suggesting that the implementation is free to clobber the
object created by the malloc() call during the interval where there's
no pointer to it. But that object has allocated storage duration (C99
6.2.4 and 7.20.3), which means that its lifetime extends from the
successful call to malloc() until the call to free(). 6.2.4p2 says:

The lifetime of an object is the portion of program execution
during which storage is guaranteed to be reserved for it. An
object exists, has a constant address, and retains its last-stored
value throughout its lifetime.

In the abstract machine, the implementation is not allowed to clobber
the allocated object during its lifetime. It can do so, via the as-if
rule, if this has no effect on the behavior of a program -- but it
would affect the program above, which does nothing that invokes
undefined behavior.
this is much the same as saying that crafting a pointer to an arbitrary area
of memory is required to work. yes, one can craft the pointer, but no, it is
not required to actually point at whatever was intended (or that it be
addressable).

An "arbitrary area of memory" is not necessarily a C object.

[...]
some restrictions may well be resonable (no serialized, misaligned, or
obfuscated pointers, ...).

Sure, but C as it is now does not impose those restrictions.
 
E

Eric Sosman

cr88192 said:
Eric Sosman said:
[... qsort() might mangle pointers _en passant_ ...]
however, we can also assume that a qsort implementation would not be
implemented in a way which is unsafe for the architecture in question...

My point is twofold: First, qsort() itself suffers no harm
if it temporarily invalidates a pointer in the act of swapping
it, even if a rogue GC comes along and incorrectly reclaims the
memory the temporarily-disguised pointer pointed at (the rest of
the program gets to deal with the consequences). Second, qsort()
(any function, for that matter) is allowed to assume that data can
be inspected and manipulated as a "bag of bytes" without harm, but
an external agency like a GC could invalidate the assumption and
strip the safety from a "perfectly safe" implementation.

Hmmm: memmove() has the same vulnerability I described for
qsort(). Again, though, it seems unlikely that GC would decide
to run in the middle of a memmove().
 
J

James Kuyper

cr88192 said:
the standards don't say they are allowed to fail, I just don't know of
anywhere where they are required, as such, to work...

The standard guarantees that you can take the value returned by a
successful call to malloc(), calloc() or realloc(), and use that value
to access the memory allocated by that call, right up until that memory
is deallocated by a call to free() or realloc(). Those guarantees impose
no requirements concerning how that value is stored. If you don't
believe that such guarantees exist, how can you dare make any use of
allocated memory? You're at just as much of a risk storing the value in
a correctly aligned pointer as storing it in a file, in unaligned
memory, or an obfuscated pointer.

If you do believe that such guarantees exist, but think that there's
something about the use of "... pointers in files, unaligned memory,
obfuscated pointers ..." which invalidates those guarantees, you should
be able to cite the relevant text which says so.
one can debate that, although they can destructure and restructure a
pointer, it says little about whatever is referenced "by" this pointer. so,
they recreate the pointer, but what is to say that the memory at this
address is required to still be valid?...

6.2.4p1: "The lifetime of an object is the portion of program execution
during which storage is guaranteed to be reserved for it. An object
exists, has a constant address,25) and retains its last-stored value
throughout its lifetime."

7.20.3: "The lifetime of an allocated object extends from the allocation
until the deallocation."
this is much the same as saying that crafting a pointer to an arbitrary area
of memory is required to work.

There's nothing arbitrary about this area of memory. It's an area of
memory that was required to hold the pointed-at object at the time the
pointer's representation was copied to other storage, and it is an area
of memory that is still required to hold that same object when that
representation is restored to a pointer object. Not because the standard
says anything about the method where by the pointer value is stored -
but because the standard does say that the implementation does not have
permission to deallocate that memory until a pointer to the the start of
that block of memory has been passed to free() or realloc().
what is to say that the app still has the same address-space layout as when
the pointer went out of visibilty?...

6.2.4p1, cited above, when it says "has a constant address".

....
some restrictions may well be resonable (no serialized, misaligned, or
obfuscated pointers, ...).

Such restrictions may well seem reasonable, but imposing such
restrictions would render invalid any claim to conform to the C
standard, specifically section 6.2.4p1.
 
C

cr88192

Golden California Girls said:
I believe you have just stated why GC can never occur on malloc'd memory.

yes, and this can also note another thing:
I have at no point been suggesting that "malloc" should be garbage
collected...
people do bad and ugly things with memory they get from malloc, and it is
usually assumed to be non-GC anyways.

so, in my case, I provide calls like gcalloc/gcfree which allocate and
(manually) free memory in the GC, and may impose a few modest restrictions,
and leave malloc/free alone for their non-GC behavior...
 
I

Ian Collins

cr88192 said:
yes, and this can also note another thing:
I have at no point been suggesting that "malloc" should be garbage
collected...
people do bad and ugly things with memory they get from malloc, and it is
usually assumed to be non-GC anyways.

so, in my case, I provide calls like gcalloc/gcfree which allocate and
(manually) free memory in the GC, and may impose a few modest restrictions,
and leave malloc/free alone for their non-GC behavior...

So

a) how does a called function know where its memory cam from?
b) how do you prevent a called function doing "bad and ugly things" with
memory allocated with gcalloc?
 
C

cr88192

James Kuyper said:
The standard guarantees that you can take the value returned by a
successful call to malloc(), calloc() or realloc(), and use that value to
access the memory allocated by that call, right up until that memory is
deallocated by a call to free() or realloc(). Those guarantees impose no
requirements concerning how that value is stored. If you don't believe
that such guarantees exist, how can you dare make any use of allocated
memory? You're at just as much of a risk storing the value in a correctly
aligned pointer as storing it in a file, in unaligned memory, or an
obfuscated pointer.

but, whoever said I was talking about memory gotten from malloc?...

malloc is outside the GC's range of responsibility, as I see it...

If you do believe that such guarantees exist, but think that there's
something about the use of "... pointers in files, unaligned memory,
obfuscated pointers ..." which invalidates those guarantees, you should be
able to cite the relevant text which says so.

maybe...



6.2.4p1: "The lifetime of an object is the portion of program execution
during which storage is guaranteed to be reserved for it. An object
exists, has a constant address,25) and retains its last-stored value
throughout its lifetime."

7.20.3: "The lifetime of an allocated object extends from the allocation
until the deallocation."

I would have to check, but if this is about malloc, see above...

I don't endorse GC'ing malloc, rather having GC as an available option, and
putting certain "sane" requirements on its use.

There's nothing arbitrary about this area of memory. It's an area of
memory that was required to hold the pointed-at object at the time the
pointer's representation was copied to other storage, and it is an area of
memory that is still required to hold that same object when that
representation is restored to a pointer object. Not because the standard
says anything about the method where by the pointer value is stored - but
because the standard does say that the implementation does not have
permission to deallocate that memory until a pointer to the the start of
that block of memory has been passed to free() or realloc().

well, this seems to be the source of confusion.
I have all along been talking about the GC, not about malloc or realloc.
rules which are specific to malloc/realloc/free thus, need not be applied to
the GC.

6.2.4p1, cited above, when it says "has a constant address".

one could have fun with this one...

...

Such restrictions may well seem reasonable, but imposing such restrictions
would render invalid any claim to conform to the C standard, specifically
section 6.2.4p1.

only if one does so with malloc...


I was never talking about malloc in this case, only about pointers (and
GC...).
 
C

cr88192

Ian Collins said:
So

a) how does a called function know where its memory cam from?
b) how do you prevent a called function doing "bad and ugly things" with
memory allocated with gcalloc?

a.
this is the responsibility of whoever wrote the code (the caller, callee, or
both...).
if the developer is a tard and uses the wrong memory in the wrong place,
that is their fault...

b.
you don't...
if the programmer is being stupid and the app crashes, that is their
fault...

add:
if one wants to try to prevent programmers from screwing up and causing
crashes, give them something other than C (like Java or similar...).


now, in an ideal world, we would tag all pointers to GC memory with a
special keyword, so that a compiler warning is given if people cast them to
an unsafe pointer or the reverse, but this is not an ideal world...

__gc void *foo;

foo=gcalloc(64);

free(foo);

Warning:foo.c:69: Implicit conversion discards '__gc'.

this way, they would need to use a cast, and less likely do stuff like this
accidentally...

 
K

Keith Thompson

Ian Collins said:
So

a) how does a called function know where its memory cam from?

It doesn't.
b) how do you prevent a called function doing "bad and ugly things"
with memory allocated with gcalloc?

You don't.

Because malloc and free have behavior defined by the standard, an
implementation is allowed to assume that they behave as specified, and
is not allowed to do things that violate their required behavior.

The behavior of gcalloc and gcfree are not defined by the standard;
they're just functions. As soon as a program calls gcalloc, the
program's behavior is no longer defined by the standard. If its
behavior changes because you temporarily scrambled a pointer, that's
too bad, but I don't think it's a conformance issue. An object
allocated by malloc has "allocated storage duration"; an object
allocated by gcalloc does not. The compiler needn't be aware that
gcalloc causes an object's lifetime to begin, or that gcfree (or an
implicit garbage collection) causes an object's lifetime to end.

If you try to replace malloc() itself with a GC-aware allocator,
*then* you run into conformance issues, and I suppose I assumed that
that was what was being discussed.
 
C

cr88192

Keith Thompson said:
It doesn't.


You don't.

Because malloc and free have behavior defined by the standard, an
implementation is allowed to assume that they behave as specified, and
is not allowed to do things that violate their required behavior.

The behavior of gcalloc and gcfree are not defined by the standard;
they're just functions. As soon as a program calls gcalloc, the
program's behavior is no longer defined by the standard. If its
behavior changes because you temporarily scrambled a pointer, that's
too bad, but I don't think it's a conformance issue. An object
allocated by malloc has "allocated storage duration"; an object
allocated by gcalloc does not. The compiler needn't be aware that
gcalloc causes an object's lifetime to begin, or that gcfree (or an
implicit garbage collection) causes an object's lifetime to end.

If you try to replace malloc() itself with a GC-aware allocator,
*then* you run into conformance issues, and I suppose I assumed that
that was what was being discussed.

yeah, people keep thinking that, I don't know why...
 
I

Ian Collins

cr88192 said:
a.
this is the responsibility of whoever wrote the code (the caller, callee, or
both...).
if the developer is a tard and uses the wrong memory in the wrong place,
that is their fault...

So GC memory can only be used with gc aware functions? That makes it
pretty restrictive.
b.
you don't...
if the programmer is being stupid and the app crashes, that is their
fault...

What if the programmer doesn't know the innards of a library function
they are calling?

[please don't quote signatures]
 
C

cr88192

Ian Collins said:
So GC memory can only be used with gc aware functions? That makes it
pretty restrictive.

many functions are safe enough that it doesn't matter...

but, where the memory came from can be considered an implicit part of its
type, and is bound by the rules of certain usage conventions.

not only do we know that a pointer points to a particular kind of struct,
but also which allocator allocated it, what its dynamic type signature is
(as a matter of convention, I use type signatures with nearly every
allocation, but this is 'gctalloc', where 'gcalloc' allocates memory but
declares it as raw unstructured memory, ...), as well as how it is to be
handled, who (if anyone), would be responsible for freeing it (usually the
caller), ...

a violation of any such detail can be considered a violation of the implicit
contract between the caller and callee...

the caller is assumed to pass something matching the expected requirements,
and the callee to do something sane with it...


but, anyways, it is all still far less restrictive than using a precise GC,
such as one where all of the references are integer handles which have to be
handled at nearly every step via special accessor functions (often wrapped
in macros).

gcp foo(gcp a, gcp b)
{
gcp c, d;
gcpBegin();
gcpArg2(a, b);
gcpVar2(c, d);
gcpSet(c, dypAdd(a, b));
gcpSet(d, dypSub(a, b));
gcpEndRet(dypList2(c, d));
}

(this level of pedantics is actually needed when multithreading,
ref-counting, and precise GC are all used in the same place...).

faced with this level of hassles, I soon reverted to using good old
conservative GC...

What if the programmer doesn't know the innards of a library function they
are calling?

that is their problem, but alas, typically one does not use GC'ed memory
with most library functions anyways, and in the cases where this is done,
one usually has a fairly good idea what the called function will do with it
(usually, in this case, it is with "raw data" functions which will likely
assume little more than to treat the memory as a raw buffer...).

to me, this is about like asking:
"what if I get this handle from the Win32 API and try to pass it into some
random OpenGL function expecting a GL handle?...", well it might work, but
the library is justified if it decides to blow up in your face for doing
something like this...

[please don't quote signatures]
ok?...
 
J

James Kuyper

cr88192 said:
but, whoever said I was talking about memory gotten from malloc?...

You, when you said:
In context, "in the first place" seemed to be referring to a context
where GC is either not supported, or at least not used by the program
being discussed. If you meant anything other than that, your comment
seems to be pointless. If that is not what you meant by "in the first
place", please explain what you did mean.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top