tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: UVM typedef struct



On Tue, Aug 11, 2009 at 03:10:11AM -0500, Peter Seebach wrote:
 > In message <20090811074826.GA16058%netbsd.org@localhost>, David Holland 
 > writes:
 >> If you don't know whether it's a pointer, you can't use it correctly,
 >> except in a very limited set of cases for very simple APIs. You get
 >> bitten by both memory management and sharing.
 > 
 > True.

Zackly :-)

 >> Consider:
 >> 
 >>    silly_t foo, bar;
 >> 
 >>    foo = get_silly_thing();
 >>    bar = foo;
 >>    change_silly_stuff(foo);
 >>    /* Ok, at this point, has bar been changed? Guess away. */
 >>    /* And for that matter, is bar even valid any more? */
 > 
 > Let's say we commit to you that, definitely, silly_t is a pointer.
 > 
 > Do you now know, without checking the API docs, whether or not bar is
 > valid?  Well, uhm.  No.

No, but if you know it's a pointer you'll go check, and ideally the
API will be designed so the name and circumstances of the call tell
you. E.g. after "silly_destroy(foo)" or "foo = munge_silly_tree(foo)"
you'd reasonably expect that bar would no longer be valid, but after
"if (is_silly_ok(foo))" you'd expect the converse. This is why it's
generally a bad idea to write functions that consume references unless
they're participating in a naming convention that makes it clear
what's going on.

Meanwhile, if you've been persuaded that silly_t is a plain value,
because you copied it obviously bar is (1) independent of foo and (2)
still valid. Which is fine if it really is... but if it's really a
pointer, (1) is certainly false and (2) may be or become false without
much warning, and then you end up in the weeds.

 > (And if the function is a function-like macro,
 > you don't even know that foo and bar are still equal.)

That's why macros of that kind are eeevil.

 > Okay, but what if we say that, for sure, silly_t is not a pointer, but an
 > opaque non-pointer object.  Now do you know?  ... Well, actually, you still
 > don't know, because it could be that silly_t is a structure CONTAINING at
 > least one pointer.  In which case bar might well now contain an invalid
 > pointer, or a pointer to an obsolete object, or... well, we just don't know.

That is a different wrong way to do things. :-)

There's no functional difference between

   typedef struct silly_thing *silly_t;

and

   typedef struct {
        struct silly_thing *thing;
   } silly_t;

and both are wrong for the same reason.

Besides, given C's type system, this way it can't be an opaque type;
in order to pass structures by value you need the size, and to do that
you need the full definition. So it's only a pretense of an opaque
type, and because of issues like the one described that's more
dangerous than leaving it exposed.

 > So in short, if types can be opaque, you have already lost.

Nah.

-- 
David A. Holland
dholland%netbsd.org@localhost


Home | Main Index | Thread Index | Old Index