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