473,394 Members | 1,717 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

Style Question - Checking for Poor Parameters

I have a general purpose library that has a lot of checks for bad input
parameters like:

void *
linkedlist_get(struct linkedlist *l, unsigned int idx)
{
if (l == NULL) {
errno = EINVAL;
return NULL;
}

if (idx >= l->size) {
errno = ERANGE;
return NULL;
}
if (idx == 0) {
return l->first->data;
...

Now in practice most of these instances would never be triggered unless
there was a flaw in the calling code in which case the program will fault
and the problem will be exposed during the testing phase. The question
is; does the user of a general purpose C library prefer these checks,
asserts, or no checks at all?

Mike
Nov 13 '05 #1
30 2194
Michael B Allen wrote:

Now in practice most of these instances would never be triggered unless
there was a flaw in the calling code
Agreed.
in which case the program will fault
and the problem will be exposed during the testing phase.
Just look at all the biggy programs out there and you can see
that this statement is false :-).

"Testing can prove the presence of bugs, but never their absence."
-- Edsger Dijkstra
The question
is; does the user of a general purpose C library prefer these checks,
asserts, or no checks at all?


You are doing the right thing.

No checking is bad because the program will continue running
with bad state and crash somewhere else. The later crash may
or may not have any relation to where the bug is. If it is
unrelated it will be very difficult to figure out where the
real bug is.

In addition, if your library is going to be used by other
people and it crashes in your code, you will be blamed for
the crash even though the other person passed in bad data.

Asserts are bad because program just prints an error message
and exits the program. This prevents the calling code from
attempting some sort of corrective action.

Erik
--
+-----------------------------------------------------------+
Erik de Castro Lopo no****@mega-nerd.com (Yes it's valid)
+-----------------------------------------------------------+
Linux: generous programmers from around the world all join
forces to help you shoot yourself in the foot for free.
Nov 13 '05 #2
Michael B Allen wrote:
I have a general purpose library
that has a lot of checks for bad input parameters like: void *
linkedlist_get(struct linkedlist *l, unsigned int idx) {
void* result = NULL;
if (NULL != l) {
if (idx < l->size) {
if (0 == idx) {
result = l->first->data;
// . . .
}
}
else { // idx >= l->size
errno = ERANGE;
}
else { // NULL == l
errno = EINVAL;
}
return result; }
Now, in practice,
most of these instances would never be triggered
unless there was a flaw (bug) in the calling code
in which case the program will fault
and the problem will be exposed during the testing phase.
The question is; does the user of a general purpose C library
prefer these checks, asserts, or no checks at all?


Use the assert C preprocessor macro
to detect programming errors (bugs).
Use the NDEBUG C preprocessor macro to turn off assert
after you have completed testing and debugging.

Use the checks above to detect *exceptions*.
(I wouldn't use errno. I'd return an exception object.)
Exceptions are expected but unpredictable events
which cannot be prevented but must be "handled"
either at the point where they are first detected
or in the calling program.
The exception object must contain *all* of the information
required to handle the exception in the calling program.

Nov 13 '05 #3
On Tue, 25 Nov 2003 15:03:49 -0500, Michael B Allen
<mb*****@ioplex.com> wrote:
I have a general purpose library that has a lot of checks for bad input
parameters like:

void *
linkedlist_get(struct linkedlist *l, unsigned int idx)
{
if (l == NULL) {
errno = EINVAL;
return NULL;
}

if (idx >= l->size) {
errno = ERANGE;
return NULL;
}
if (idx == 0) {
return l->first->data;
...

Now in practice most of these instances would never be triggered unless
there was a flaw in the calling code in which case the program will fault
and the problem will be exposed during the testing phase. The question
is; does the user of a general purpose C library prefer these checks,
asserts, or no checks at all?


As someone who has used and written quite a few libraries, I've found
it most helpful for them to return a status code which can be tested,
and to provide a function to convert the status code to a string.

When it's appropriate for a lot of related functions to return
pointers, providing a library_geterror() routine is an option as well.

I prefer libraries not use errno (except of course the standard
library). Most libraries need to report errors other than the C
standard errors. Also, it's often useful to call standard library
functions during error logging or reporting, and having to shuffle
errno is a PITA.

In complex libraries, especially those dealing with unpredicatable
external data, I like being able to set error and warning callbacks as
well.

I wouldn't recommend assert() for *external* sanity checks if other
people will be using your library. It's fine for internal stuff,
though.

- Sev

Nov 13 '05 #4
"E. Robert Tisdale" wrote:
Michael B Allen wrote:
I have a general purpose library
that has a lot of checks for bad input parameters like:

void *
linkedlist_get(struct linkedlist *l, unsigned int idx) {
void* result = NULL;
if (NULL != l) {
if (idx < l->size) {
if (0 == idx) {
result = l->first->data;
// . . .
}
}
else { // idx >= l->size
errno = ERANGE;
}
else { // NULL == l
errno = EINVAL;
}
return result;

}


No he didn't write that. Not only are you a consumate idiot in
the C advice you give, you are systematically misstating what
others wrote for your own trollish purposes.

This systematic altering of someone elses words is far worse, in
my mind, than any other sins Trollsdale has committed here. The
others can be put down to stupidity, ignorance, and poor
upbringing, but this goes far beyond the pale.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #5
On Wed, 26 Nov 2003 05:00:16 GMT, CBFalconer <cb********@yahoo.com>
wrote:
"E. Robert Tisdale" wrote:
Michael B Allen wrote:
> I have a general purpose library
> that has a lot of checks for bad input parameters like:

> void *
> linkedlist_get(struct linkedlist *l, unsigned int idx) {
> void* result = NULL;
> if (NULL != l) {
> if (idx < l->size) {
> if (0 == idx) {
> result = l->first->data;
> // . . .
> }
> }
> else { // idx >= l->size
> errno = ERANGE;
> }
> else { // NULL == l
> errno = EINVAL;
> }
> return result;

}


No he didn't write that. Not only are you a consumate idiot in
the C advice you give, you are systematically misstating what
others wrote for your own trollish purposes.

This systematic altering of someone elses words is far worse, in
my mind, than any other sins Trollsdale has committed here. The
others can be put down to stupidity, ignorance, and poor
upbringing, but this goes far beyond the pale.


I briefly wondered why it looked different, but I didn't actually
reread the code. I assumed it was just a newsreader-formatting-flub.

ERT wouldn't last a week at my company. What horrid code! What a tard!

- Sev

Nov 13 '05 #6
On Tue, 25 Nov 2003 16:55:54 -0500, Erik de Castro Lopo wrote:

No checking is bad because the program will continue running with bad
state and crash somewhere else. The later crash may or may not have any
relation to where the bug is. If it is unrelated it will be very
difficult to figure out where the real bug is.
Not necessarily. Dereferecing NULL is going to fault on the spot.
In addition, if your library is going to be used by other people and it
crashes in your code, you will be blamed for the crash even though the
other person passed in bad data.
Not necessarily :-) There are quite a few well known or standard library
functions that expect suitable inputs.
Asserts are bad because program just prints an error message and exits
the program. This prevents the calling code from attempting some sort of
corrective action.


Agreed. It's hard to ship code with asserts. Certainly not mature code.

Well I think I'm going to stick with leaving the checks as it is obvious
there is no consensus on this issue.

Mike
Nov 13 '05 #7
On Tue, 25 Nov 2003 17:28:45 -0500, Severian wrote:
As someone who has used and written quite a few libraries, I've found it
most helpful for them to return a status code which can be tested, and
to provide a function to convert the status code to a string.
I have macros and some functions for doing just that. I just don't do
it from trivial things like the linkedlist example shown.
When it's appropriate for a lot of related functions to return pointers,
providing a library_geterror() routine is an option as well.

I prefer libraries not use errno (except of course the standard
library). Most libraries need to report errors other than the C standard
errors. Also, it's often useful to call standard library functions
during error logging or reporting, and having to shuffle errno is a
PITA.


For non-trivial stuff yes. If for no other reason that errno clashes
with reentrant code (which I think is basically what you just said). For
trivial stuff like a linkedlist ADT it's hard to justify adding an error
code member to struct linkedlist.

Mike
Nov 13 '05 #8
On Wed, 26 Nov 2003 04:17:27 -0500, Michael B Allen
<mb*****@ioplex.com> wrote:
On Tue, 25 Nov 2003 17:28:45 -0500, Severian wrote:
As someone who has used and written quite a few libraries, I've found it
most helpful for them to return a status code which can be tested, and
to provide a function to convert the status code to a string.
I have macros and some functions for doing just that. I just don't do
it from trivial things like the linkedlist example shown.


I do too, and write them specifically for imported libraries when
needed. Like you, I don't use others' libraries for trivial things
like linked lists; but I understood the question as applying to much
more general (and more widely distributed) libraries.
When it's appropriate for a lot of related functions to return pointers,
providing a library_geterror() routine is an option as well.

I prefer libraries not use errno (except of course the standard
library). Most libraries need to report errors other than the C standard
errors. Also, it's often useful to call standard library functions
during error logging or reporting, and having to shuffle errno is a
PITA.


For non-trivial stuff yes. If for no other reason that errno clashes
with reentrant code (which I think is basically what you just said).


Yes, reentrancy (and threads) are things I have to deal with. But I
was simply thinking of a library returning an error that I need to
report: the reporting process may require me to call standard library
functions before using errno, which could overwrite errno. So, even in
the absence of reentrancy or threads, I would have to remember to copy
its value to another variable. Not a big deal, but something not
necessary if the library routines return their own status codes.
For
trivial stuff like a linkedlist ADT it's hard to justify adding an error
code member to struct linkedlist.
Absolutely! I wouldn't think of using someone else's library for
something as trivial as that, and I would code my one quite
differently. Again, I viewed his sample code as showing some things a
"general purpose" library routine could check for. I suppose I read
that as something that lots of other people would be using.
Mike


Nov 13 '05 #9
Stop fighting kids. I'm sure you're all talented programmers but the way how
some people deal with each other is horrible. Get off that computer and
learn some basic social stuff first, that's what makes us differ from
animals.

Greetinsg,
Rick
Nov 13 '05 #10
"Rick" <as******@hotmail.com> wrote:

[Please keep some context, including attributions, when replying; it
makes it much easier for others to follow discussions. Thank you.]
Stop fighting kids. I'm sure you're all talented programmers but the way how
some people deal with each other is horrible. Get off that computer and
learn some basic social stuff first, that's what makes us differ from
animals.


Neither of them is a kid. And E.R.T. is a well known troll who
regularly alters quoted text without indication, in order to mess
up usenet discussions. That's not just a Bad Thing[tm], it's
abusive behaviour.

My 0.02 EUR.

Regards
--
Irrwahn
(ir*******@freenet.de)
Nov 13 '05 #11
In <3f**********************@news.xs4all.nl> "Rick" <as******@hotmail.com> writes:
Stop fighting kids. I'm sure you're all talented programmers but the way how ^^^^some people deal with each other is horrible. Get off that computer and
learn some basic social stuff first, that's what makes us differ from
animals.


You may want to follow your own advice.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #12
On Wed, 26 Nov 2003 04:49:15 -0500, Severian wrote:
standard errors. Also, it's often useful to call standard library
functions during error logging or reporting, and having to shuffle
errno is a PITA.


For non-trivial stuff yes. If for no other reason that errno clashes
with reentrant code (which I think is basically what you just said).


Yes, reentrancy (and threads) are things I have to deal with. But I was
simply thinking of a library returning an error that I need to report:
the reporting process may require me to call standard library functions
before using errno, which could overwrite errno. So, even in the absence
of reentrancy or threads, I would have to remember to copy its value to
another variable.


I don't really follow. Consider setlocale. It has a tendency to set
errno as it searchs and fails to find various locale files even though
it ultimately returns success. If I call that, it sets errno, and I do
something else that can set errno then at no point do I need to save
errno as you describe. Either I return success in which case the caller
should happily proceed or I return -1 indicating errno should be examined
at which point it should be what I set it to when the error occured
(e.g. EIO).

int
my_fn(char *l)
{
setlocale(LC_ALL, l);

if (another_fn() == -1) {
errno = EIO;
return -1;
}

return 0;
}

Otherwise, it is very poor design IMO to require checking errno to
determine if an error occured. Occationally it is unreasonable to
do otherwise but in this case an error member specific to the object
associated with the error should be used with an additional function to
retrieve it (e.g. fread).

Can you be more specific about where you would be compelled to "shuffle
errno"?

Mike
Nov 13 '05 #13
Irrwahn Grausewitz <ir*******@freenet.de> scribbled the following:
"Rick" <as******@hotmail.com> wrote:
[Please keep some context, including attributions, when replying; it
makes it much easier for others to follow discussions. Thank you.]
Stop fighting kids. I'm sure you're all talented programmers but the way how
some people deal with each other is horrible. Get off that computer and
learn some basic social stuff first, that's what makes us differ from
animals.

Neither of them is a kid. And E.R.T. is a well known troll who
regularly alters quoted text without indication, in order to mess
up usenet discussions. That's not just a Bad Thing[tm], it's
abusive behaviour. My 0.02 EUR.


But he didn't call them kids. He asked them to stop fighting kids. I
think that's wise. After all, the kids are hardly a match for them,
are they?

--
/-- Joona Palaste (pa*****@cc.helsinki.fi) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"'I' is the most beautiful word in the world."
- John Nordberg
Nov 13 '05 #14
On 26 Nov 2003 20:58:49 GMT, Joona I Palaste <pa*****@cc.helsinki.fi>
wrote:
Irrwahn Grausewitz <ir*******@freenet.de> scribbled the following:
"Rick" <as******@hotmail.com> wrote:
[Please keep some context, including attributions, when replying; it
makes it much easier for others to follow discussions. Thank you.]

Stop fighting kids. I'm sure you're all talented programmers but the way how
some people deal with each other is horrible. Get off that computer and
learn some basic social stuff first, that's what makes us differ from
animals.

Neither of them is a kid. And E.R.T. is a well known troll who
regularly alters quoted text without indication, in order to mess
up usenet discussions. That's not just a Bad Thing[tm], it's
abusive behaviour.

My 0.02 EUR.


But he didn't call them kids. He asked them to stop fighting kids. I
think that's wise. After all, the kids are hardly a match for them,
are they?


But talented programmers have to do *something* for relaxation! You
have to admit that fighting kids is basic social stuff, after all, and
it does get one off the computer. I'm not so sure it differentiates us
from animals, though. Most of us actually are animals, though there
may be some vegetative tendencies here and there.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 13 '05 #15
Michael B Allen wrote:

On Tue, 25 Nov 2003 16:55:54 -0500, Erik de Castro Lopo wrote:

No checking is bad because the program will continue running with bad
state and crash somewhere else. The later crash may or may not have any
relation to where the bug is. If it is unrelated it will be very
difficult to figure out where the real bug is.


Not necessarily. Dereferecing NULL is going to fault on the spot.


But what if the NULL pointer is passed into the library which
stores it for use later. It is this later use of an unvalidated
pointer which will cause the segfault and then you need to
figure out how the NULL pointer got to its present state.
In addition, if your library is going to be used by other people and it
crashes in your code, you will be blamed for the crash even though the
other person passed in bad data.


Not necessarily :-) There are quite a few well known or standard library
functions that expect suitable inputs.


As an author of two widely used Free Software libraries I can
assure you that it you remove the possibility of your software
being blamed you will have a much easier time of supporting
it :-).

Erik
--
+-----------------------------------------------------------+
Erik de Castro Lopo no****@mega-nerd.com (Yes it's valid)
+-----------------------------------------------------------+
Peter F. Curran : Microsoft. Still delivering a text editor with
Win95/98 that can only open a max 64K file, despite being on
a machine with an 8Gig HD and 64M of ram....
G Cook: Perhaps, but Notepad is still the most functional program
in the whole suite!
Nov 13 '05 #16
Joona I Palaste <pa*****@cc.helsinki.fi> wrote:
Irrwahn Grausewitz <ir*******@freenet.de> scribbled the following:
"Rick" <as******@hotmail.com> wrote:
Stop fighting kids. I'm sure you're all talented programmers but the way how
some people deal with each other is horrible. Get off that computer and
learn some basic social stuff first, that's what makes us differ from
animals.

Neither of them is a kid. And E.R.T. is a well known troll who
regularly alters quoted text without indication, in order to mess
up usenet discussions. That's not just a Bad Thing[tm], it's
abusive behaviour.


But he didn't call them kids. He asked them to stop fighting kids. I
think that's wise. After all, the kids are hardly a match for them,
are they?


I don't know about his strength, though. However, maybe he had
only one comma left and thought it would look better in the second
sentence... <g,d&r>
--
Irrwahn
(ir*******@freenet.de)
Nov 13 '05 #17
On Wed, 26 Nov 2003 14:27:54 -0500, Michael B Allen
<mb*****@ioplex.com> wrote:
On Wed, 26 Nov 2003 04:49:15 -0500, Severian wrote:
standard errors. Also, it's often useful to call standard library
functions during error logging or reporting, and having to shuffle
errno is a PITA.

For non-trivial stuff yes. If for no other reason that errno clashes
with reentrant code (which I think is basically what you just said).


Yes, reentrancy (and threads) are things I have to deal with. But I was
simply thinking of a library returning an error that I need to report:
the reporting process may require me to call standard library functions
before using errno, which could overwrite errno. So, even in the absence
of reentrancy or threads, I would have to remember to copy its value to
another variable.


I don't really follow. Consider setlocale. It has a tendency to set
errno as it searchs and fails to find various locale files even though
it ultimately returns success. If I call that, it sets errno, and I do
something else that can set errno then at no point do I need to save
errno as you describe. Either I return success in which case the caller
should happily proceed or I return -1 indicating errno should be examined
at which point it should be what I set it to when the error occured
(e.g. EIO).

int
my_fn(char *l)
{
setlocale(LC_ALL, l);

if (another_fn() == -1) {
errno = EIO;
return -1;
}

return 0;
}

Otherwise, it is very poor design IMO to require checking errno to
determine if an error occured. Occationally it is unreasonable to
do otherwise but in this case an error member specific to the object
associated with the error should be used with an additional function to
retrieve it (e.g. fread).

Can you be more specific about where you would be compelled to "shuffle
errno"?


It's pretty contrived, but this should show what I mean:

if (my_fun("somestring") < 0) {
FILE *flog = fopen("error.log", "a+"); /* errno may be gone! */
if (flog) {
fprintf(flog, "my_fun reports: %d\n", errno);
fclose(flog);
}
return FALSE;
}

- Sev
- Sev

Nov 13 '05 #18
Michael B Allen <mb*****@ioplex.com> wrote in message news:<pa*********************************@ioplex.c om>...
I have a general purpose library that has a lot of checks for bad input
parameters like:

[snip]

The only problem I can see is if one of your functions calls another
one of your functions and both of them check for bad input, so you
might be testing for the same kind of invalid input twice.
Nov 13 '05 #19
On Wed, 26 Nov 2003 17:11:17 -0500, Severian wrote:
Can you be more specific about where you would be compelled to "shuffle
errno"?


It's pretty contrived, but this should show what I mean:

if (my_fun("somestring") < 0) {
FILE *flog = fopen("error.log", "a+"); /* errno may be gone! */ if
(flog) {
fprintf(flog, "my_fun reports: %d\n", errno); fclose(flog);
}
return FALSE;
}


Ahh. I see what you mean.

Mike
Nov 13 '05 #20
On Wed, 26 Nov 2003 04:12:34 -0500, Michael B Allen wrote:
On Tue, 25 Nov 2003 16:55:54 -0500, Erik de Castro Lopo wrote:

No checking is bad because the program will continue running with bad
state and crash somewhere else. The later crash may or may not have any
relation to where the bug is. If it is unrelated it will be very
difficult to figure out where the real bug is.


Not necessarily. Dereferecing NULL is going to fault on the spot.


Define "fault". If you mean "cause a segfault and the app will instantly
stop executing", I point you to, among others, DOS - in which you can
often happily dereference NULL without the application so much as
hiccupping.
Nov 13 '05 #21
"Kelsey Bjarnason" <ke*****@lightspeed.bc.ca> wrote in message
news:pa****************************@lightspeed.bc. ca...
On Wed, 26 Nov 2003 04:12:34 -0500, Michael B Allen wrote:
On Tue, 25 Nov 2003 16:55:54 -0500, Erik de Castro Lopo wrote:

No checking is bad because the program will continue running with bad
state and crash somewhere else. The later crash may or may not have any
relation to where the bug is. If it is unrelated it will be very
difficult to figure out where the real bug is.


Not necessarily. Dereferecing NULL is going to fault on the spot.


Define "fault". If you mean "cause a segfault and the app will instantly
stop executing", I point you to, among others, DOS - in which you can
often happily dereference NULL without the application so much as
hiccupping.


It depends on the target platform and how the compiler implements
NULL internally. In the source code, NULL is zero. The compiler is
allowed to use any internal bit representation it wants for NULL
that it (the compiler) won't confuse with a valid pointer. Many
compilers simply use binary zero, which is fine with me, but for
portability I must remember that an internal NULL is not
necessarily zero.

Location zero may be accessible, depending on the target platform,
so the programmer should not rely on the machine to detect
dereferencing a NULL pointer.
Nov 13 '05 #22
"xarax" <xa***@email.com> wrote in message news:<kG*******************@newsread1.news.pas.ear thlink.net>...
"Kelsey Bjarnason" <ke*****@lightspeed.bc.ca> wrote in message
news:pa****************************@lightspeed.bc. ca...
On Wed, 26 Nov 2003 04:12:34 -0500, Michael B Allen wrote:
Not necessarily. Dereferecing NULL is going to fault on the spot.

It depends on the target platform and how the compiler implements


FWIW, Unix on some (DEC?) machines, IIRC, stored 0 at location 0.
Thus, the code
if (p == NULL || *p == 0)
return FAILURE;
could be "optimized" to just
if (*p == 0)
return FAILURE;

(In a vaguely similar vein, Data General machines had special addresses
where *p automatically became (*p)++ or (*p)--, and special pointers
where *p automatically became **p.)

Don't blame any of this on me, please; I'm just reporting
historical trivia.

James
Nov 13 '05 #23
In <kG*******************@newsread1.news.pas.earthlin k.net> "xarax" <xa***@email.com> writes:
It depends on the target platform and how the compiler implements
NULL internally. In the source code, NULL is zero.


Nope, it's a four letter identifier. And there is no way to guess into
what the preprocessor will expand it.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #24
On Sat, 29 Nov 2003 17:24:43 -0800, Kelsey Bjarnason
<ke*****@lightspeed.bc.ca> wrote:
On Wed, 26 Nov 2003 04:12:34 -0500, Michael B Allen wrote:
On Tue, 25 Nov 2003 16:55:54 -0500, Erik de Castro Lopo wrote:

No checking is bad because the program will continue running with bad
state and crash somewhere else. The later crash may or may not have any
relation to where the bug is. If it is unrelated it will be very
difficult to figure out where the real bug is.


Not necessarily. Dereferecing NULL is going to fault on the spot.


Define "fault". If you mean "cause a segfault and the app will instantly
stop executing", I point you to, among others, DOS - in which you can
often happily dereference NULL without the application so much as
hiccupping.

In fact, I've used implementations which filled the area around *NULL
with special values, then reported a "NULL pointer error" if one of
those locations had changed at program exit.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 13 '05 #25
Erik de Castro Lopo <no****@mega-nerd.com> wrote in message news:<3F***************@mega-nerd.com>...
Michael B Allen wrote:
<snipped post about whether or not to check for arguments>

You are doing the right thing.

No checking is bad because the program will continue running
with bad state and crash somewhere else. The later crash may
or may not have any relation to where the bug is. If it is
unrelated it will be very difficult to figure out where the
real bug is.

In addition, if your library is going to be used by other
people and it crashes in your code, you will be blamed for
the crash even though the other person passed in bad data.

I think a little differently here.
Checking for errors = Good Thing.
Checking for bad args = It Depends.

Your function takes a pointer argument, right ? if the caller
passes a bad argument, how does it help to check the argument
for NULL ? out of the millions of different bad values that
the argument could possibly hold, you only check for one.

more to the point, the single check you make is for a value
(if the argument was not static at callers end) that will
possibly only result if the caller *explicitly* sets
it to that value.

If your library is going to be used by other people, then
make sure you document the behaviour of the functions when
the arguments are bad. then their code must play properly
with your code, e.g.

/* my header file for libfoo */
/* foo_1 results in UB if arg1 is an invalid
pointer, or if arg1 cannot be dereferenced.
*/
int foo_1 (char *arg1);

/* foo_2 will return the number of arguments
processed *IF* the argument list consists
entirely of valid pointers *AND* is terminated
by a NULL pointer *AND* has at least one
(possibly NULL) argument.
*/
int foo_1 (char *first_arg, ...);

you cannot stop the users of your library crashing
their program. If they cannot understand that
an argument should not be NULL, and pass it anyway,
its still all going to end in tears for them when
they (sooner or later) violate some other library.
Asserts are bad because program just prints an error message
and exits the program. This prevents the calling code from
attempting some sort of corrective action.


I never use asserts of any sort, although I am quite
fond of writing a DIAGNOSTIC() macro whenever I start
work on a new architecture.

hth
goose,
some people have it coming to them, I'm only
a delivery mechanism :-).
Nov 13 '05 #26
In <ff**************************@posting.google.com > ru**@webmail.co.za (goose) writes:
Erik de Castro Lopo <no****@mega-nerd.com> wrote in message news:<3F***************@mega-nerd.com>...
Michael B Allen wrote:
<snipped post about whether or not to check for arguments>

You are doing the right thing.

No checking is bad because the program will continue running
with bad state and crash somewhere else. The later crash may
or may not have any relation to where the bug is. If it is
unrelated it will be very difficult to figure out where the
real bug is.

In addition, if your library is going to be used by other
people and it crashes in your code, you will be blamed for
the crash even though the other person passed in bad data.


I think a little differently here.
Checking for errors = Good Thing.
Checking for bad args = It Depends.


Indeed. Checking for bad args makes sense only if it can be done in
a thorough manner and if the function specification promises such checks.
Your function takes a pointer argument, right ? if the caller
passes a bad argument, how does it help to check the argument
for NULL ? out of the millions of different bad values that
the argument could possibly hold, you only check for one.


Furthermore, these checks are not free. Why penalise the performance
of the correct programs, that never pass bad arguments, for the sake of
the broken programs, that do? It is the caller who has to decide whether
the value of the argument needs to be checked before being passed to the
callee. Because the caller has enough information to:

1. Decide whether the check is necessary at all.

2. Perform the check in a thorough manner.

Note that the specification of the standard C library doesn't require
such checks and few (if any) actual implementations perform them. For
the reasons described above.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #27
On 2 Dec 2003 17:33:50 GMT, Da*****@cern.ch (Dan Pop) wrote:
In <ff**************************@posting.google.com > ru**@webmail.co.za (goose) writes:
Erik de Castro Lopo <no****@mega-nerd.com> wrote in message news:<3F***************@mega-nerd.com>...
Michael B Allen wrote:
<snip>
In addition, if your library is going to be used by other
people and it crashes in your code, you will be blamed for
the crash even though the other person passed in bad data.

It saves a lot of finger-pointing and having to prove things -- even
in some cases when I'm both the finger-pointer and -pointee!
I think a little differently here.
Checking for errors = Good Thing.
Checking for bad args = It Depends.
Indeed. Checking for bad args makes sense only if it can be done in
a thorough manner and if the function specification promises such checks.
Your function takes a pointer argument, right ? if the caller
passes a bad argument, how does it help to check the argument
for NULL ? out of the millions of different bad values that
the argument could possibly hold, you only check for one.


In one library I wrote (more detail below), I check a specific pointer
for:

1. NULL pointer.
2. On platforms where the check is available and inexpensive: writable
data at the address, and at address + structure length - 1.
3. Valid contents in some key portions of the structure.
Furthermore, these checks are not free. Why penalise the performance
of the correct programs, that never pass bad arguments, for the sake of
the broken programs, that do? It is the caller who has to decide whether
the value of the argument needs to be checked before being passed to the
callee. Because the caller has enough information to:

1. Decide whether the check is necessary at all.

2. Perform the check in a thorough manner.
Sometimes only the callee has the information necessary for either. In
a database layer I wrote (and use regulary), a context block is
returned to the caller when the database is opened, somewhat analogous
to a FILE *. The caller uses this context block in subsequent calls
for database access.

Since the caller has no knowledge of the layout or contents of the
context block, each externally-callable routine in my library
validates it -- not completely thoroughly (see above), but well enough
that most possible problems are detected early. This helps when a bug
does occur; rather than some obscure crash deep within the bowels of
the database software, the library returns an error immediately.
Note that the specification of the standard C library doesn't require
such checks and few (if any) actual implementations perform them. For
the reasons described above.


For me, it depends on the scope of the library. The more complex the
library (and the more libraries it is in turn depenent upon), the more
likely that errors caused by bad arguments will be difficult to track
down, especially in multi-threaded or asynchronous operation. And, at
least in my example case, the cost of the validation is essentially
unmeasurable, since the functions themselves are so much more
expensive.

Of course, in many other libraries I've written, I perform no argument
validation at all. It always depends!

- Sev

Nov 13 '05 #28
On 26 Nov 2003 16:08:01 -0800, de********@yahoo.com (Debashish
Chakravarty) wrote:
Michael B Allen <mb*****@ioplex.com> wrote in message news:<pa*********************************@ioplex.c om>...
I have a general purpose library that has a lot of checks for bad input
parameters like:

[snip]

The only problem I can see is if one of your functions calls another
one of your functions and both of them check for bad input, so you
might be testing for the same kind of invalid input twice.


In a case where I feel that argument validation is imperative, only
the calls availble externally perform validation; internally, the
library doesn't ever call those routines.

- Sev

Nov 13 '05 #29
Joona I Palaste <pa*****@cc.helsinki.fi> wrote in message news:<bq**********@oravannahka.helsinki.fi>...
Irrwahn Grausewitz <ir*******@freenet.de> scribbled the following:
"Rick" <as******@hotmail.com> wrote:
[Please keep some context, including attributions, when replying; it
makes it much easier for others to follow discussions. Thank you.]

Stop fighting kids. I'm sure you're all talented programmers but the way how
some people deal with each other is horrible. Get off that computer and
learn some basic social stuff first, that's what makes us differ from
animals.

Neither of them is a kid. And E.R.T. is a well known troll who
regularly alters quoted text without indication, in order to mess
up usenet discussions. That's not just a Bad Thing[tm], it's
abusive behaviour.

My 0.02 EUR.


But he didn't call them kids. He asked them to stop fighting kids. I
think that's wise. After all, the kids are hardly a match for them,
are they?


it depends; are they having a battle of the wits with kids, or
physical fighting ?

goose,
some usenet posters I know are no match for some
of the kids I know, in wit(less) battles :-)
Nov 13 '05 #30
Alan Balmer <al******@att.net> wrote in message news:<3r********************************@4ax.com>. ..
On 26 Nov 2003 20:58:49 GMT, Joona I Palaste <pa*****@cc.helsinki.fi>
wrote:
Irrwahn Grausewitz <ir*******@freenet.de> scribbled the following:
"Rick" <as******@hotmail.com> wrote:
[Please keep some context, including attributions, when replying; it
makes it much easier for others to follow discussions. Thank you.] Stop fighting kids. I'm sure you're all talented programmers but the way how
some people deal with each other is horrible. Get off that computer and
learn some basic social stuff first, that's what makes us differ from
animals. Neither of them is a kid. And E.R.T. is a well known troll who
regularly alters quoted text without indication, in order to mess
up usenet discussions. That's not just a Bad Thing[tm], it's
abusive behaviour. My 0.02 EUR.


But he didn't call them kids. He asked them to stop fighting kids. I
think that's wise. After all, the kids are hardly a match for them,
are they?


But talented programmers have to do *something* for relaxation! You
have to admit that fighting kids is basic social stuff, after all, and
it does get one off the computer. I'm not so sure it differentiates us
from animals, though. Most of us actually are animals, though there
may be some vegetative tendencies here and there.


handy rule: if you start leaning towards sunlight, its time
for more meat in your diet :-)

goose,
Nov 13 '05 #31

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Tongu? Yumruk | last post by:
I have a little proposal about type checking in python. I'll be glad if you read and comment on it. Sorry for my bad english (I'm not a native English speaker) A Little Stricter Typing in Python...
4
by: Tuure Laurinolli | last post by:
Someone pasted the original version of the following code snippet on #python today. I started investigating why the new-style class didn't work as expected, and found that at least some instances...
4
by: lawrence | last post by:
Can anyone tell me why this code works in Netscape 7.1 but not in IE??? <SCRIPT type='text/javascript'> function makeVisible(nameOfDiv) {...
28
by: Michael B. | last post by:
I tend to use rather descriptive names for parameters, so the old style of declaration appeals to me, as I can keep a declaration within 80 chars: void * newKlElem...
83
by: rahul8143 | last post by:
hello, what is difference between sizeof("abcd") and strlen("abcd")? why both functions gives different output when applied to same string "abcd". I tried following example for that. #include...
43
by: Sensei | last post by:
Hi! I'm thinking about a good programming style, pros and cons of some topics. Of course, this has nothing to do with indentation... Students are now java-dependent (too bad) and I need some...
20
by: Xiaoshen Li | last post by:
Hi, I am reading the book "Concepts of programming languages" by R. W. Sebesta. He said: "One of the most important reasons why C is both liked and disliked is its lack of complete type...
18
by: Joel Hedlund | last post by:
Hi! The question of type checking/enforcing has bothered me for a while, and since this newsgroup has a wealth of competence subscribed to it, I figured this would be a great way of learning...
5
by: rconradharris | last post by:
A co-worker of mine came across some interesting behavior in the Python interpreter today and I'm hoping someone more knowledgeable in Python internals can explain this to me. First, we create...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.