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

C

cr88192

James Kuyper said:
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.

C running on just the raw CPU with no MM, such as in an OS kernel, ...
in this case, it is primarily a matter of the CPU architecture.


for example, if a pointer/integer/... is misaligned, many archs will refuse
to access it (and on others, such as x86, it comes with a minor performance
hit, but the CPU can be set up to generate an interrupt in response if
desired...).

similarly, an obfuscated pointer will typically blow up if one tries to
deference it absent restoring it to its original form.

pointers in files tend to break as it is often not the case that subsequent
runs of a program have exactly the same memory layout.

....


so, as a simplifying assumption, we can say:
all pointers are required to be properly aligned in memory and in an
unaltered form.
compiler-generated code almost universally follows this rule (the exception
being with "__attribute__((packed))" or similar...).

as a result, one can safely say that pointers need to be aligned, and
reasonably expect the compiler to maintain this.

scanning misaligned memory is thus, not worth the 4 or 8x slowdown, in
practice, and we can allow this as an edge case in which the GC is allowed
to fail. reasonably written code will not try to do this anyways.
 
J

jameskuyper

cr88192 said:
C running on just the raw CPU with no MM, such as in an OS kernel, ...
in this case, it is primarily a matter of the CPU architecture.


for example, if a pointer/integer/... is misaligned, many archs will refuse
to access it (and on others, such as x86, it comes with a minor performance
hit, but the CPU can be set up to generate an interrupt in response if
desired...).

Has anyone suggested otherwise? I assumed that your mention of
"unaligned storage" was referring to copying a pointer into
incorrectly aligned storage (as might happen when packing a struct)
and then restoring it to correctly aligned storage before attempting
to dereference it - has anyone actually suggested attempting to
dereference such a pointer before realigning it? Does it cause any
less of a problem for GC if it is realigned before usage?
similarly, an obfuscated pointer will typically blow up if one tries to
deference it absent restoring it to its original form.

Well, certainly. Has anyone suggested trying to use an obfuscated
pointer without first restoring the original form? Does it cause any
less of a problem for GC if it is restored to it's original form
before being dereferenced?
pointers in files tend to break as it is often not the case that subsequent
runs of a program have exactly the same memory layout.

Well, certainly - such pointers can only be used while the program
that wrote the pointer is still running, and the object that it
originally pointed to has not yet ended it's lifetime. Has anyone
suggested otherwise? Does it cause any less of a problem for GC if it
is only used before the end of that lifetime?
so, as a simplifying assumption, we can say:
all pointers are required to be properly aligned in memory and in an
unaltered form.

It's perfectly feasible to use each of the techniques listed above to
side-step this "requirement", so long as you pay close attention to
the actual requirements for doing so safely.

As long as you're aware that this requirement is entirely an artifact
of your simplification, and has no basis in reality, that's fine.
Otherwise it's like making the simplification "human beings have two
legs", and then using that simplification to justify asserting that
people cease to be human when they lose one or more of their legs.
compiler-generated code almost universally follows this rule

Human-generated code follows that "rule" too - not because it's
actually a rule, but because reasons justifying violation of that non-
rule are rare.
as a result, one can safely say that pointers need to be aligned, and
reasonably expect the compiler to maintain this.

Yes. But more importantly, we can also expect that any compiler
claiming to conform to the standard will allow all three of the
techniques mentioned above to work properly, if done in the correct
fashion.

My very first message on this subthread described my understanding of
what you were talking about as follows:
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 you weren't actually talking about restoring the original pointer
a) in correctly aligned memory
b) with it's original object representation
c) during the lifetime of the pointed-at object

then you should have commented on my description with a more detailed
explanation of what you were actually talking about. But I find it
hard to see how idiotic code attempting to use pointers that haven't
been properly restored has anything to do with the context in which
you made that statement.
 
C

cr88192

jameskuyper said:
Has anyone suggested otherwise? I assumed that your mention of
"unaligned storage" was referring to copying a pointer into
incorrectly aligned storage (as might happen when packing a struct)
and then restoring it to correctly aligned storage before attempting
to dereference it - has anyone actually suggested attempting to
dereference such a pointer before realigning it? Does it cause any
less of a problem for GC if it is realigned before usage?

if the pointer is misaligned in the first place, it is likely that someone
will try to use it misaligned, otherwise there is not much reason for it to
be misaligned in the first place (apart from the possible buffer-copying
example, which would place the restriction that the buffer "should" be
aligned...).

but, mostly I am concerned with things likely to happen in practice, not as
much with esoteric edge cases...

Well, certainly. Has anyone suggested trying to use an obfuscated
pointer without first restoring the original form? Does it cause any
less of a problem for GC if it is restored to it's original form
before being dereferenced?

yeah, even if restored, obfuscated pointers may be missed by the GC.
if being used, a person would need to use them with non-GC memory...

however, the issue here is that there is no simple or effective algorithm I
am aware of for dealing with this case in a GC, making the point moot.

Well, certainly - such pointers can only be used while the program
that wrote the pointer is still running, and the object that it
originally pointed to has not yet ended it's lifetime. Has anyone
suggested otherwise? Does it cause any less of a problem for GC if it
is only used before the end of that lifetime?

but then why would anyone be writing the pointer to a file?...

it is usually the case that files are used with the intention of persistent
storage, and so, there is not so much reason to write a pointer to a file
and not expect it to remain intact between runs...

It's perfectly feasible to use each of the techniques listed above to
side-step this "requirement", so long as you pay close attention to
the actual requirements for doing so safely.

not necessarily, or at least not in a concurrent GC...

that is, the main app thread and GC thread may be "doing their thing" at the
same time...
(the other case would involve needing to pause all the "managed" threads
prior to running the GC, which has been a temptation at times...).

technically, it is not safe to handle GC'ed memory in any thread not
originally created by the GC (apart from the "main" thread, which is handled
specially, as well as the GC's internal threads, ...).

As long as you're aware that this requirement is entirely an artifact
of your simplification, and has no basis in reality, that's fine.
Otherwise it's like making the simplification "human beings have two
legs", and then using that simplification to justify asserting that
people cease to be human when they lose one or more of their legs.

it has a basis in reality:
performance and implementability of the GC...


using this example and means of arguing:
because some people may lack legs, that means no one should use stairs...

yet one can clearly see that stairs are the accepted means of going up and
down between floors, ... (well, that, elevators, and escalators... where in
the airport I had seen occasional wheelchairs going up and down on the
escalators...).

but, whether to do something funky with pointers is a programmer choice, not
a physical disability...

Human-generated code follows that "rule" too - not because it's
actually a rule, but because reasons justifying violation of that non-
rule are rare.

ok.



Yes. But more importantly, we can also expect that any compiler
claiming to conform to the standard will allow all three of the
techniques mentioned above to work properly, if done in the correct
fashion.

with malloc...

otherwise, it depends on the specifics of the runtime functions used...

My very first message on this subthread described my understanding of
what you were talking about as follows:


If you weren't actually talking about restoring the original pointer
a) in correctly aligned memory
b) with it's original object representation
c) during the lifetime of the pointed-at object

then you should have commented on my description with a more detailed
explanation of what you were actually talking about. But I find it
hard to see how idiotic code attempting to use pointers that haven't
been properly restored has anything to do with the context in which
you made that statement.

I think context has been lost along the way.
I would have to look back to see whether the context was GC'ed memory or
malloc'ed memory...

(my thinking is that the pointer may disappear or reappear, but this does
not necessarily related to the pointed to memory, rather to the
representation of the pointer / its memory address...).


but, oh well, whatever...
 
J

jameskuyper

cr88192 said:
if the pointer is misaligned in the first place, it is likely that someone
will try to use it misaligned, otherwise there is not much reason for it to
be misaligned in the first place (apart from the possible buffer-copying
example, which would place the restriction that the buffer "should" be
aligned...).

but, mostly I am concerned with things likely to happen in practice, not as
much with esoteric edge cases...

Misaligned pointers in packed structures do happen in practice, though
not perhaps frequently enough for you to care about.

....
yeah, even if restored, obfuscated pointers may be missed by the GC.

If they're kept in obfuscated form long enough, this becomes a near-
certainty.
if being used, a person would need to use them with non-GC memory...

however, the issue here is that there is no simple or effective algorithm I
am aware of for dealing with this case in a GC, making the point moot.

But the point is precisely that GC can't handle it, so I don't see how
that could render it moot.
but then why would anyone be writing the pointer to a file?...

You brought up the writing of pointers to files, not me. Even without
GC, there's no way to make use of a pointer stored in a file to access
an object, once the objects it points to has ended its lifetime. It's
not merely unportable, it's virtually guaranteed not to work;
therefore I assumed that you were talking about writing pointers to a
file and using them only during the lifetime of the object pointed at.

The most plausible reason I can think of to do it is if there's
insufficient room to keep everything in memory, and the decision is
made to move some of the data out of memory and into a file for
temporary storage. This duplicates the purpose of a typical virtual
memory manager, so it would only be worthwhile when VM is either
unavailable, or has problems that render it unattractive. Obviously,
you would need to make sure that the object which the pointer is
pointing at is not also moved off into the file.

....
not necessarily, or at least not in a concurrent GC...

I thought that your point was that the such techniques "... are ..
not ... really required to work in the first place", and that GC could
therefore be implemented without imposing any new requirements.
Certainly such requirements could be added as part of adding GC, but
that did not seem to be what you were saying.

....
it has a basis in reality:
performance and implementability of the GC...

It's an additional requirement added by the GC, not one that already
exists "in the first place".
using this example and means of arguing:
because some people may lack legs, that means no one should use stairs...

No, I'm not arguing that it wouldn't be possible to add GC to the
language and impose the corresponding requirements on it's use. I'm
arguing against the claim that GC adds no new requirements, because
such techniques supposedly "... are .. not ... really required to work
in the first place".
I think context has been lost along the way.
I would have to look back to see whether the context was GC'ed memory or
malloc'ed memory...

The context is the message you wrote which contains the header "Date:
Sun, 26 Apr 2009 13:57:47 -0700".
As I've already pointed out: if your statement was not meant to apply
to a program where GC is unused, it's not at all clear what it was
supposed to mean, or how it was supposed to support your overall
argument.
 
C

CBFalconer

cr88192 said:
.... snip ...

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.

Since malloc is necessarily system sensitive, you can't do that and
omit having gcalloc call malloc to get the memory. Otherwise you
can't be writing portable code.
 
C

CBFalconer

cr88192 said:
.... snip ...

so, as a simplifying assumption, we can say:
all pointers are required to be properly aligned in memory and in
an unaltered form. compiler-generated code almost universally
follows this rule (the exception being with
"__attribute__((packed))" or similar...).

as a result, one can safely say that pointers need to be aligned,
and reasonably expect the compiler to maintain this.

scanning misaligned memory is thus, not worth the 4 or 8x
slowdown, in practice, and we can allow this as an edge case in
which the GC is allowed to fail. reasonably written code will not
try to do this anyways.

How do you know a pointer is 'aligned'? This is one of the reasons
malloc has to be a system function.
 
C

cr88192

CBFalconer said:
Since malloc is necessarily system sensitive, you can't do that and
omit having gcalloc call malloc to get the memory. Otherwise you
can't be writing portable code.

yes, but using malloc at the back end is not really an issue...

but, as can be noted, portability is a bit of an issue with conservative
GC's, as in, many seemingly simple tasks depend on lots of system dependent
stuff, so one ends up needing a bunch of arch-specific ifdef's and similar.

among these is that malloc is generally not used for getting memory (due to
other reasons), rather it is more common to use 'mmap()' or 'VirtualAlloc()'
or similar...
 
C

cr88192

CBFalconer said:
How do you know a pointer is 'aligned'? This is one of the reasons
malloc has to be a system function.

typically the compiler keeps things aligned.
typically malloc keeps memory aligned, and so putting a struct in malloc'ed
memory also keeps it aligned.

though not strictly portable, it is not too difficult to manaually align
addresses to particular boundaries...

 
C

CBFalconer

cr88192 said:
yes, but using malloc at the back end is not really an issue...

but, as can be noted, portability is a bit of an issue with
conservative GC's, as in, many seemingly simple tasks depend on
lots of system dependent stuff, so one ends up needing a bunch of
arch-specific ifdef's and similar. among these is that malloc is
generally not used for getting memory (due to other reasons),
rather it is more common to use 'mmap()' or 'VirtualAlloc()' or
similar...

This is c.l.c. There are no such functions as mmap or VirtualAlloc
in standard C. malloc (and friends, such as calloc and realloc)
are the only way of securing arbitrary chunks of memory.
 
C

CBFalconer

cr88192 said:
typically the compiler keeps things aligned. typically malloc
keeps memory aligned, and so putting a struct in malloc'ed
memory also keeps it aligned.

though not strictly portable, it is not too difficult to
manaually align addresses to particular boundaries...

True. However, it is totally impossible to discover what those
alignment requirements are in a portable manner.
 
C

cr88192

CBFalconer said:
This is c.l.c. There are no such functions as mmap or VirtualAlloc
in standard C. malloc (and friends, such as calloc and realloc)
are the only way of securing arbitrary chunks of memory.

but, muwahaha, I am posting from comp.lang.misc...

 
C

cr88192

Golden California Girls said:
CBF is going to throw a fit. A call to a not standard function got
mentioned.
I bet he says it won't work and that it is illegal and off topic.

Actually this kind of proves that it is rather impossible to use standard
C to
write some programs. Not sure about most of you but I tend to want my
languages
to be able to express all concepts, although some do it much easier than
others.
Therefore ISO C should be depreciated. <:p


yeah, some things just can't be done with malloc, like getting chunks of
memory you can safely write machine code into and call into via function
pointers...

in some cases it may work (x86 with no DEP), but if one uses x86-64 or has
application-level DEP turned on, it may well blow up.

well, as well as GUIs, using the soundcard, 3D graphics, ...

so, yeah, most real code ends up with arch specific chunks and a whole lot
of ifdef's...
 
C

cr88192

CBFalconer said:
True. However, it is totally impossible to discover what those
alignment requirements are in a portable manner.

maybe, but on most archs there are special defines to tell which arch as
being used.

#ifdef linux
#ifdef __i386__
....
#endif
#ifdef __ppc64__
....
#endif
#endif

....
 
C

CBFalconer

cr88192 said:
.... snip ...

but, muwahaha, I am posting from comp.lang.misc...

All right, we will forgive you this time. :) We should curse the
idiot who cross-posted this to c.l.c.
 

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,076
Latest member
OrderKetoBeez

Latest Threads

Top