Coding practices proposals

Greg Hudson ghudson at MIT.EDU
Fri Mar 18 15:38:07 EDT 2011

On Fri, 2011-03-18 at 14:59 -0400, Nico Williams wrote:
> I much prefer having a single lexical scope for all owner pointer
> variables in functions, with one goto label for all cleanup.  I'd even
> prefer if all such variables were always initialized to NULL where
> declared and then have free() called unconditionally on each of those
> variables' values in the cleanup section.  Alias and non-pointer
> variables should be OK to declare in inner scopes.  Whenever an
> pointer ownership is transferred the old owner should be set to NULL.
> This style makes it much easier to get a high degree of confidence
> that there are no memory leaks and no double frees.

Full agreement, with the proviso that I don't see much point in nulling
out owner variables which immediately go out of scope or get destroyed.

I think this paragraph is mostly representative of the middle of the
road consensus of the thread so far.  Sam and Ken are more partial to
inner-scope variable declarations; Tom and I would probably prefer to
never use them.

> You might even want to have a naming convention (a common affix) for
> owner pointer variables.

Not sold on this at the current time; I see the benefit but for the
moment I think the verbosity cost outweighs it.

>   I'd rather there never were any pointer
> aliases as structure fields -- always dup objects instead or else use
> reference counting.

We use aliases a lot when we construct a temporary structure on the
sack, use it, and then throw it away.  For instance, when converting a
null-terminated string to a krb5_data to pass to some function which
needs it.  C strings aren't reference counted and copying the string
would be verbose and wasteful.  This pattern also arises in functions
like krb5_mk_req where we are generating the encoding of a structure and
then throwing away the structure.

I think it's reasonably safe to create structures full of aliases.  Once
you start mixing aliases and owner fields within the same structure, I
think it becomes hard to verify the correctness of a function, though.

> Also, all output arguments MUST be initialized on function entry, even
> if the documentation says that output values are undefined in error
> cases.

Yeah, this is already a documented practice, although not all of our
code conforms.

>   (Also, on when you know you're in the client-side I'd rather
> assert() than return EINVAL-like errors when functions are used
> incorrectly, but this is too difficult to do in a krb5 library, so, oh
> well.)

This practice is unfriendly to libraries which might have bindings in
safe languages, unless the bindings can trivially ensure the validity of
the arguments.

> I don't personally care for having a naming convention for
> distinguishing output arguments from others as long as the types used
> make it obvious which arguments are inputs and which are outputs.
> E.g., if the output arguments are all of the form "type **" (or
> "pointer_type *") and all input arguments have fewer '*'s in their
> types, then there's no need to add an "_out" suffice to the output
> arguments.  Avoid using arguments for input and output.

Noted.  Our historical practice of filling in caller-provided structure
containers (especially krb5_data) often makes it unclear what's an input
and what's an output.  If we stick to outputting pointers, it's a little
clearer until you start getting into sequences (like "krb5_padata **in,
krb5_padata ***out").

More information about the krbdev mailing list