-
-
Notifications
You must be signed in to change notification settings - Fork 452
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make attributes preceed function declarations
This also adds soem additional ATTR_ONNULL and ATTR_RETNONNULL markers that were absent previously. The order for attributes is roughly: noreturn, format, nonnull, returns_nonnull, malloc, alloc_size, access
- Loading branch information
Showing
1 changed file
with
36 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
398fb30
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@BenBE May I suggest to remove some of the
nonnull
attributes on these functions?Some of the
nonnull
attributes added in this commit 398fb30 might look too strict for what the function was designed.full_write
- I suggest to removeATTR_NONNULL
and just leaveATTR_ACCESS3_R(2, 3)
in place. The function was designed that a zero-size write is allowed (it just does nothing), and thatATTR_ACCESS3_R(2, 3)
would be sufficient for the sanity check.full_write_str
. That is,full_write_str
should keepATTR_NONNULL
.sumPositiveValues
- I suggest to removeATTR_NONNULL
and just leaveATTR_ACCESS3_R(1, 2)
in place. When I wrote thissumPositiveValues
function, I expectedcount
argument being zero is valid use.ATTR_ACCESS3_R(1, 2)
would be enough for the sanity check.398fb30
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With both
full_write
andsumPositionalValues
you still can have thesize
/count
be specified as0
. The only limitation whichATTR_NONNULL
has on the function declaration is forcing all provided pointers to be non-NULL
. You still can dofull_write(file, some_buffer, 0);
as long assome_buffer
points to a valid memory address. The implication of theATTR_ACCESS_R(2,3)
alone would be that I could dofull_write(NULL, NULL, 0);
which is wrong in one instance (the file argument should be non-NULL, always) and surprising on a second front (the buffer is NULL, which won't matter because it should never be accessed). Having theATTR_NONNULL
here avoids both cases. One could argue refull_write(file, NULL, 0)
but IMHO that's surprising and at least inviting to cause errors in other parts of the code.398fb30
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@BenBE Well, the first argument of
full_write
is anint
type FD, not a pointer type, so theATTR_NONNULL
can't apply to it. That only leaves the secondbuffer
argument whichATTR_NONNULL
can apply to.My concern is that the
buffer
andsize
arguments might come from objects or structures whose members are left uninitialized (NULL pointers and zero size) for any reason. If we applyATTR_NONNULL
, we risk letting compiler over-optimize things (e.g. with code that always de-reference the pointer while it's not safe to do so).For
sumPositiveValues
in particular, I did anticipatesumPositiveValues(NULL, 0)
can happen, for example in this code:You may argue that the meters without numeric items to draw all have their "Bar" display mode disabled, but I am trying to be cautious here, and don't like the function to be optimized with a stricter constraint that I didn't intend to have at the beginning.
398fb30
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ATTR_NONNULL
is not only about optimization, but also on constraint checking. If you can have a NULL passed in which the caller doesn't check, the compiler will usually tell you about this constraint violation (I even had the compiler produce multi-page diagnostics about a possible NULL de-reference across compilation unit boundaries purely based on the non-NULL attribute of one function argument). Yes, it won't do this reliably in all cases and also not if you don't do global optimizations, but even then having the attributes marked rather consistently will provide you with quite a lot of benefits.In the end,
ATTR_NONNULL
is about the contract to the caller and declaring "I don't want you to pass a NULL value here" is a definite contract to the caller which when violating causes undefined behaviour (which may result in a crash).So if your caller in
Meter_computeSum
passes that valuethis->values
tosumPositiveValues
without ensuring a non-NULL value, that's a violation from the caller.FWIW, if you involve undefined behaviour, don't expect the compiler to do anything in particular. For all intents and purposes, if the compiler were to decide the undefined behaviour could best be realized by formatting your hard-drive, this would fully be correct by the definition of the C standard; just probably not what you intended for your code to do.
Or to summarize: If you aren't sure, you always pass non-NULL pointers along, check them before passing them. If the compiler notices they could not have been NULL (because of another
ATTR_NONNULL
in effect) it will tell you. Try to be defensive with your code; and if you can check for non-NULLs automatically with the compiler then that's a benefit you should embrace.398fb30
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@BenBE I mean that passing
this->values
tosumPositiveValues
whenthis->values
is NULL should be allowed as long asthis->curItems
is zero. The only constraint for theMeter_computeSum
function mentioned isthis
must be non-null. WithATTR_NONNULL
added tosumPositiveValues
, it could break that use case by turning an allowed behavior into an undefined one.398fb30
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And my stand on this is that
Meter_computeSum
is responsible for proper checking of arguments andsumPositiveValues
does not acceptNULL
s and thus should never see them …398fb30
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@BenBE That would be additional code than I initially intended.
The code would become this...
While for the original
sumPositiveValues
code, it should be fine for the call likesumPositiveValues(NULL, 0)
, in which case it returns0.0
:398fb30
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or simply:
398fb30
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@BenBE For code size, I would rather not do that redundant
this->curItems
check and just go with this: