When to check the return value of malloc

T

Tim Harig

elegance?

Funny that you do not make any comments where I placed my counter-example
you might as well argue that { and } and we should all code in Pascal
(actually I /do/ think we should all code in pascal, but that's
another issue :) )

I also code in Ada. I have not problems with begin/end style syntax; but,
{} works just as well for me. The difference is that I see less abuse of
{} then I do of ?:.
rather depends on the code base doesn't it?

1. Reference: _Writing Solid Code_ by Steve Maguire, "The ?: is an If
Statement Too", p.127-130 and "APL Syndrome", p.161-162

2. I have too much experience with programmers abusing ?: only to write
errors. When I rewrite the code using if/else syntax and give them both
copies, they see their own errors much faster using the normal if/else
syntax.
do you have figures from cognitive scientists and psychologists?

I have 1 expert opinion, quite a bit of person experience with poorly
written ?: constructs, and another simple demonstration. Properly blocked
and indented code, even smeared out so the text and operators are not
visual, provides a number of clues about the code. This technique has been
used in studies for testing the readability of different indent styles and
block layouts.

See _Code Complete_ by Steve McConnell, section 18.2-4 "Layout
Techniques", p.408-410; section 18-3 "Layout Styles", p.410-417; and
section 18.4 "Laying Out Control Structures" p.417-425.

Using this method if/if else/else control structures are clearly visible in
the code even though the actual operators are obscured. ?:'s on a single
line just look like statements. Furthermore, the indentation style is
consistant with the style of the rest of the control statements used in the
code. ?: breaks this consistancy.
not really. I was always a fan of Algol-60s (and Coral's)

x := if a = b then 1 else 2;

that is they used the same keywords for both if/elses. Only yesterday
I was arguing with someone who said this was a bad idea and the two
forms /should/ be distinguished.

The ?: implies that a value is changing. That isn't always the case.
Sometimes you just want to use a different set of steps based on the
conditional. ?:, because it implys this changing value, doesn't work
clearly in this condition. If/else handles this flawlessly.
 
R

Richard Bos

bart.c said:
I use this construction all the time, although mostly in a different
language and mostly associated with strings (when there are two or more in
the same expression). An example in C might be:

printf("%d %s in %d
Director%s\n",nfiles,(nfiles=1?"File":"Files"),ndirs,(ndirs=1?"y":"ies"));

Yes, but in that case - at least, with saner spatiation - the meaning of
the ?:s is directly apparent. Each of them is a simple, obvious binary
choice. I'd prefer to see it written like this, though:

printf("%d File%s in %d Director%s\n", nfiles, nfiles=1?"" :"s",
ndirs, ndirs=1 ?"y":"ies");

(although my indentation is, in this case, geared specifically towards
this one case; if the two ?:s weren't so directly parallel, I'd move
ndirs et seq. further left.)

The point is, though, that this is much different from a more involved
and seemingly random

f( p+(a?b:c)+q*(d?e:g))

which does _not_ tell you what the ?:s mean at all.

Richard
 
T

Tim Harig

Simpler, more readable code, as there's only one assignment to
each of the intermediate values rather than two.

Here you have small point; however, it doesn't overcome the list of other
points against it such as lack of layout consistency, the requirement for
reading separate operators, the missuse of code packed to tightly as part
of "APL Syndrome", the lack of clear established reason when being used as
part of complex statements.
Simpler, more readable code, as the definition of the intermediate
values is accompanied by the initialisation thereof.

Nobody commented on my main argument at
<[email protected]> where this was addressed.
People tend to use ?: as part of expressions without proper documentation
as to why they are using it. This is less likely to happen when used as a
separate block unit which can understood separately and is more likely to
be commented properly.
A couple of lines in a
source code file? A couple hours pay finding a bug because somebody
overlooked the conditional as a simple statement [rearranged back to original form]
, while quickly scanning the code?

The whole point of the statement is the conditional expression -
anyone who's going to overlook that has no right to be looking
at the code.

Even looking at properly formated source code which has been blacked
out so that only the whitespace is visible, it is possible to see the
conditionals because of their indent styles. ?: breaks this; Using the
same method, ?: will almost always be confused for a simple statement
because it does not follow the same indent pattern. Consistency is
desireable in its own right; but, in this case it is easy and I have seen
good programmers miss ?:'s while scanning code because it doesn't have the
same indented block pattern as every other control structure.
Care to cite any scientific studies that back up that claim?
You may get confused by ?:, but I've got a multimegaline codebase
at $DAYJOB which proves that your weakness isn't shared by too
many people.

I referenced sections of Code Complete in
<[email protected]> regarding the benefits of
if/else's consistancy of layout style. The sections referenced themselves
reference several studies on the benefits of block layout and indention.
Since ?: is almost always used without this layout structure, it looses
those benefits.

As for being used in your codebase, I am saying ?: is impossible to parse;
but, that doesn't mean its use is any clearer then just using if/else.
Why require someone to match the targets of two separate assignments?
And why require people to separate definition from initialisation?

I actually don't have as much of a problem with ?: being used in an
initialization where the variable is declared *if* the declarations are in
the proximity of the code block where it is used as it is possible to do
using C99 to avoid variable persistance. When used at the top of functions as
is required by C89, it would be placing a conditional well away from the
rest of the code where the variable is used which is a bad thing. I will
tentatively accept this; because, have not seen it abused whereas I have seen ?:
fully abused in code blocks. I reserve the right to change my mind if I do
ever see it overly abused. Personally, I am not really sure why you need
to conditionally initialize a variable when it is declared. Generally, you
don't change the initialization, you change it when it becomes necessary to
do so in your code blocks.
Goto can do things that cannot legibly be done with if/else,
so why require someone reading your code to read two different
types of control flow when one will handle them both. (Included
ironically purely to show how flawed your logic is.)

I don't have as much of a problem with goto used properly. No, it should
not be used to implement loops; but, it is useful for handling errors in
nested loops. Goto is not conditional so it cannot be used for if/else
replacement even if there was some good reason to do so.
 
B

bart.c

Richard Bos said:
Yes, but in that case - at least, with saner spatiation - the meaning of
the ?:s is directly apparent. Each of them is a simple, obvious binary
choice. I'd prefer to see it written like this, though:

printf("%d File%s in %d Director%s\n", nfiles, nfiles=1?"" :"s",
ndirs, ndirs=1 ?"y":"ies");
The point is, though, that this is much different from a more involved
and seemingly random

f( p+(a?b:c)+q*(d?e:g))

which does _not_ tell you what the ?:s mean at all.

It wasn't meant to be meaningful, only to be an example awkward to convert
into if-else statements. I'm sure there must be real expressions with more
than one ?: operation.

As for my printf example being a series of binary selections: that example
was derived from this non-C fragment that used *3* of these constructs, but
I couldn't convert the first bit into C cleanly:

display((nfiles|str(nfiles)|"No") + (nfiles=1|" File"|" Files") + " in " +
str(ndirs) + " Director"+(ndirs=1|"y"|"ies"))

(Here, (a|b|c) just means a?b:c.)

It's clearly just a status message being constructed, nothing momentous.

It could be decomposed but there seems little point.
 
T

Tim Harig

Note that this changes the way something is calculated which will be used
somewhere else in the execution of the program. (see below)
I use this construction all the time, although mostly in a different
language and mostly associated with strings (when there are two or more in
the same expression). An example in C might be:

printf("%d %s in %d
Director%s\n",nfiles,(nfiles=1?"File":"Files"),ndirs,(ndirs=1?"y":"ies"));

Fair enough, this is a different usage then above because you are not
actually going to be changing any persistant values which may be used later
in the program. I would accept this; although, I am assuming that you have
already check for 0 and negative values elsewhere in your code.
What comments would be needed in examples such as above?

I would agree that this is pretty self explanitory. The example where you
used conditionals inside of a calculation statement was not.
You are so impressed that you saved a little bit of typing; but, what
happens down the road when we find that there are three numbers that could
be associated with x or that if a, we really need to do three things to
know that x should be?

Well in another language I would use: m:=(n|"One","Two","Three"|"Other")...

In C, you might use: m = (n>=1 && n<=3 ? table[n] : "Other");

But, this involves setting up the table[] data, which is a nuisance if it is
only used in this one place. So this is more an argument for extending the
?: feature into a multi-selection operator...

1. This only works for the multivalue case; not where you have to insert
more code because it now requires more then a simple assignment.

2. C does not have a multi-selection operator so the point is mute.
Your solution would presumably be:

switch (n) {
case 1: m="One"; break
case 2: m="Two"; break
case 3: m="Three"; break
default: m="Other";
}
Which would be a major distraction when your code has bigger fish to fry
than just setting a variable to one of 4 values...

Since you did not provide an example in C, I can only speculate that your
solution would have included nesting ?: statements. Once again this isn't
scalable and looses the consitancy and clarity that comes with if/else (or
a *properly indented* switch/case).
 
B

bart.c

Perhaps I should have explained better: a?b:c is little different from
table[a]. So you are also asking why I need to total values under M*N
different circumstances, which is nonsense.
I would accept this; although, I am assuming that you have
already check for 0 and negative values elsewhere in your code.

0 is OK ("0 files"; "No files" is better but more fiddly to achieve in one
line)
-N is also OK ("-5 files", which just indicates a problem elsewhere)
what
happens down the road when we find that there are three numbers that
could
be associated with x or that if a, we really need to do three things to
know that x should be?

Well in another language I would use:
m:=(n|"One","Two","Three"|"Other")...

In C, you might use: m = (n>=1 && n<=3 ? table[n] : "Other");
Your solution would presumably be:

switch (n) {
....

Since you did not provide an example in C, I can only speculate that your
solution would have included nesting ?: statements.

I gave my C version above for an indexed selection, but using an array (and
needing to explicitly check range) instead of being to express all the
possibilities in situ.

Where nested ?: are called for, it will be complicated, but if/else
versions, especially with distinct ?: blocks on the same line, will also be.
Some judgement is needed as to the best approach. Just outlawing ?:
completely doesn't seem sensible.
Once again this isn't
scalable and looses the consitancy and clarity that comes with if/else (or
a *properly indented* switch/case).

?: chains can also be laid out with indentation. As I said, judgement is
used when writing code.
 
T

Tim Harig

Perhaps I should have explained better: a?b:c is little different from
table[a]. So you are also asking why I need to total values under M*N
different circumstances, which is nonsense.

If you had used table[a] it would have made your code clearer and you would
not have had to give the explanation that you are now. I would have known
from your descriptive variable name table that the operation is simply
taking something from a table. If table is well named
ie, "plural_eqivilants_table" then I understand exactly why I could
by using different values in the first place.

The variable name "a" is still ambiguous, I don't really know why I am
choosing one value or another out of the table; but, that is a different
problem altogether.

?: shows what you are doing. Using a table tells me not only what you are
doing but why you are doing it.
0 is OK ("0 files"; "No files" is better but more fiddly to achieve in one
line)
-N is also OK ("-5 files", which just indicates a problem elsewhere)

If negative numbers indicates a problem then it should have been check as
an error; or, it would indicate an error in the code. If it indicates an
error in the code, it would be wise to add an assertion to make sure it is
detected should that problem ever exist.
what
happens down the road when we find that there are three numbers that
could
be associated with x or that if a, we really need to do three things to
know that x should be?

Well in another language I would use:
m:=(n|"One","Two","Three"|"Other")...

In C, you might use: m = (n>=1 && n<=3 ? table[n] : "Other");
Your solution would presumably be:

switch (n) {
...

Since you did not provide an example in C, I can only speculate that your
solution would have included nesting ?: statements.

I gave my C version above for an indexed selection, but using an array (and
needing to explicitly check range) instead of being to express all the
possibilities in situ.

So, when this happened you needed to revert to using another method. If
you had been using the table method (or even a chained if/else if/else)
this would not require any more work then adding a value to the table.
That was my point in the first place.

You still did not address the situation where the statement requires more
operations then a simple assignment. In this situation, a table may not be
sufficient to handle all of the possible execution paths. This is an
equally relavant change that is would require the modification of the
statement since it is tied to the conditional.
Where nested ?: are called for, it will be complicated, but if/else
versions, especially with distinct ?: blocks on the same line, will also be.

I *never* advocate using if/else on the same line. I don't advocate ?:
anywhere. I never would have had this issue in the first place because I
never used the ?: to start with.
Some judgement is needed as to the best approach. Just outlawing ?:
completely doesn't seem sensible.

Since if/else can do everything ?: can I don't see any reason to advocated
the use of ?:. I have never seen an example where if/else could not be
used or where it was not at least as clear is ?:. If ?: could do
everything as clearly as ?:, then I would say choose one of the two and
stick with it. There is no need to have code littered with both. As it
is, if/else is more general. Since we only need on, I choose the more
general of the two.
?: chains can also be laid out with indentation. As I said, judgement is
used when writing code.

Yes they can, but what have you gained. All that you really have done is
chagned if to ? and else to :. Furthermore, ?: *implies* an assignment.
What about code where not assignemnt takes place?

if (condition) {
/* do something without an assignment */
print_report();
else
/* do something else without an assignment */
print_error_report()

Yes you could use ?:; but it would be an abuse of the nature of the
operators and therefore misleading to anybody who has to read the code.
 
B

bart.c

Tim Harig said:
Tim Harig said:
On 2010-05-17, bart.c <[email protected]> wrote:
f( p+(a?b:c)+q*(d?e:g))
then I'd really like to see your version using if/else.

Ignoring the visual clues provided by the indentation that there is a
divergence of execution control, your complex statment, while
contrived,
doesn't explain why you are doing what you are doing. Why is it that
you
might need to total what amounts to different values under *four*
different
circumstances?

Perhaps I should have explained better: a?b:c is little different from
table[a]. So you are also asking why I need to total values under M*N
different circumstances, which is nonsense.

If you had used table[a] it would have made your code clearer and you
would
not have had to give the explanation that you are now.

I disagree. a?b:c can be done as an array (assuming for a minute that a=0 or
1 and that b and c are constants):

int table[2]={b,c};

x=table[a]; /* instead of x=a?b:c; */

But isn't it much clearer when all the possibilies for table are laid out
for you directly in the expression?
?: shows what you are doing. Using a table tells me not only what you are
doing but why you are doing it.

You're getting extra information from the superfluous table name, but also
hiding the contents of the table as well as generating extra clutter. You
might as well insert an embedded comment.
I *never* advocate using if/else on the same line. I don't advocate ?:
anywhere.

I meant when an expression has multiple lots of possibly nested ?:, the
if/else equivalents would be equally tortured code.
Yes they can, but what have you gained. All that you really have done is
chagned if to ? and else to :. Furthermore, ?: *implies* an assignment.
What about code where not assignemnt takes place?

Huh? Where does it say that ?: is associated with assignments? ?: is used
just like any other operator, while indentation might be used like this
(imagine a,b,c are more complex than they are).:

p->q->r = a
?b
:c
if (condition) {
/* do something without an assignment */
print_report();
else
/* do something else without an assignment */
print_error_report()

Yes you could use ?:; but it would be an abuse of the nature of the
operators and therefore misleading to anybody who has to read the code.

There's no point using ?: here, as they confer little benefit. But there are
plenty if situations where they *are* useful:

p[sourceix?i:j] = q[destix?i:j];
 
S

sandeep

Eric said:
Also, some realloc() implementations will *always* move the region,
even when shrinking it or when there happens to be a "gap" right after
it. And then they'll fill the old region with 0xDEADBEEF or some such.
Can you guess why a realloc() implementor would choose to do this?

Please do not patronize me Mr Susman.
Ponder this, Sandeep: How did the computer know it should emit
a "Floating point exception" message? What prompted it do do so?

A hardware trap led to a SIGFPE signal being sent by the kernel. I do not
believe the compiler generated any code to catch division by 0 in
software.
All of these functions have well-defined behaviors when the
argument/operand is a null pointer. So does free().

If so then in my opinion this is a deficiency in the definition of C.
Passing a NULL pointer to free should yield an undefined behavior in my
opinion.
 
T

Tim Harig

Tim Harig said:
Perhaps I should have explained better: a?b:c is little different from
table[a]. So you are also asking why I need to total values under M*N
different circumstances, which is nonsense.

If you had used table[a] it would have made your code clearer and you
would
not have had to give the explanation that you are now.

I disagree. a?b:c can be done as an array (assuming for a minute that a=0 or
1 and that b and c are constants):

int table[2]={b,c};

x=table[a]; /* instead of x=a?b:c; */

But isn't it much clearer when all the possibilies for table are laid out
for you directly in the expression?

Not necessarily, if the function of the table is obvious I should not need
to know what it contains. Moreover, I shouldn't need to consern myself
if it changes.

b and c need not be constants. In your singular vs plural example, they
could easily be redefined for new languages etc.

Note that the table was your idea and one that it turns out that I really
do like. I was simply going to stick with an if/else; but, I like your
idea better. There is one raw edge. Because you used an array for your
table, your code is subject overflow if a is set incorrectly. This is easy
to fix with a simple function wrapper for table[a] that asserts a is within
the range that it should be.

I really like this. We have turned an obscure operation into a scalable,
flexible, descriptive abstraction that has the added benefit of helping
us in our code testing. What could be better?
You're getting extra information from the superfluous table name, but also
hiding the contents of the table as well as generating extra clutter. You
might as well insert an embedded comment.

On the contrary, moving implementation details behind abstractions so
that they only need to thought of or modified in one place is very much
the spirit behind structured programming.

A comment is not optional here; but, comments have a bad habit of not being
updated and they do not excuse poor code.
I meant when an expression has multiple lots of possibly nested ?:, the
if/else equivalents would be equally tortured code.

A properly written and formated if/else chain is not "tortured;" but, yes
if the ?: chain is broken down over multiple lines and it only leads to
assignments then they are not much different. This has been one of my
large themes since the beginning. You are not really gaining anything with
?: but you can loose with it.
Yes they can, but what have you gained. All that you really have done is
chagned if to ? and else to :. Furthermore, ?: *implies* an assignment.
What about code where not assignemnt takes place?

Huh? Where does it say that ?: is associated with assignments? ?: is used
just like any other operator, while indentation might be used like this
(imagine a,b,c are more complex than they are).:

p->q->r = a
?b
:c


Notice that r is being assigned a value here. My point was, what if there
is no assignment being made? The code just branches to do different tasks.
The code below was designed as an example.
There's no point using ?: here, as they confer little benefit. But there are
plenty if situations where they *are* useful:

Here we agree and it makes my point directly above.
p[sourceix?i:j] = q[destix?i:j];

Once again, I am left without any evident clues as to why we might be using
branching values for these indexes. You have saved a few lines at the cost
of code clarity. This is back where we started in the first place. Yes,
its true that ?: isn't always unreadable; but, it doesn't really save you
anything except a little typing even where these conditions occur.

I have already shown you that even where there is no clarity breakdown, and
these are few (definitly *not* the preceding example), it makes the code
harder to modify. There is no doubt that it breaks the consistancy of
conditional indenting. (Remember that many languages do not support ?: but
that almost every language supports an if/else.)

No, ?: is no more evil then goto. A properly written goto can *enhance*
readablity and the logical flow; but, we also know that the true niche for
a goto is rare. It actually provides a benefit that does not exist in any
other construct. Thanks to the stigma that surrounds it, it is much less
abused. We have learned to make sure that there is very careful
consideration before using it because, while it is not inherently evil, we
have learned to distrust the individual programmer's disgression of when it
is beneficial to use and when it is not.

Where goto provides additonal functionality, ?: does not provide any
real benefit over a traditional if/else construct. It is used simply to
save fingers from typing. Yes it can be spread over multiple lines; but,
people rarely do. Yes there are times when it make make sense to use; but,
I have learned programmer disgression is not so great at making these
descisions.

While we cannot replace the functionality we have received with goto, the
same cannot be said of ?:. Since it is redundant, since is well known to
create clarity issues without significant benefit, since it is less
scalable and more poorly used, since it is replacable; I say avoid it.
 
S

Seebs

Please do not patronize me Mr Susman.

And yet, you can't spell his name, and you regularly say things that are
frankly pretty dumb.
A hardware trap led to a SIGFPE signal being sent by the kernel. I do not
believe the compiler generated any code to catch division by 0 in
software.

Maybe, maybe not. So what?
If so then in my opinion this is a deficiency in the definition of C.

Are you a sock for Nilges, that you think that when you're flatly wrong
about C, that's a defect in the language?
Passing a NULL pointer to free should yield an undefined behavior in my
opinion.

And yet, you've never supported this opinion. There's a number of good
reasons for the current behavior. Some early C implementations (pre-standard)
did in fact crash on free(NULL). It was a serious pain, because it
dramatically amplified a fairly common class of bugs, and didn't really
offer any benefits.

You haven't offered any real explanation for why free(NULL) shouldn't be
defined to just do nothing. The only explanation on offer is that it's
purely a matter of your ego -- you are too proud to admit that you were
wrong.

This makes it pretty pointless for anyone to try to help you learn C; you've
already committed yourself to not learning.

-s
 
K

Keith Thompson

sandeep said:
Please do not patronize me Mr Susman.

Please do not patronize the rest of us. (And his name is Sosman,
not Susman.)
A hardware trap led to a SIGFPE signal being sent by the kernel. I do not
believe the compiler generated any code to catch division by 0 in
software.

It doesn't matter whether the compiler generated code to catch it.
The compiler generated code that resulted in the division by zero
being caught. The implementation is more than the compiler, and the
compiler is perfectly free to take advantage of the characteristics
of the underlying system (in fact it must do so).

Of course there's no requirement in C for checks on floating-point
operations (except, I suppose, in certain IEEE modes; I don't
recall the details). The point is that, in the example you chose
to support your claim that there was no check for division by zero,
*there was a check for division by zero*.
If so then in my opinion this is a deficiency in the definition of C.
Passing a NULL pointer to free should yield an undefined behavior in my
opinion.

And you're certainly entitled to that opinion. But please sit
back for a moment and ponder the fact that a number of people who
have far more C experience than you strongly disagree with you.
Does it even occur to you that you might be wrong?

Once you've done that, you might want to answer the question I
asked you in Message-ID: <[email protected]>,
<http://groups.google.com/group/comp.lang.c/msg/bddfd7151e3ca10f>.
 
E

Eric Sosman

A hardware trap led to a SIGFPE signal being sent by the kernel. I do not
believe the compiler generated any code to catch division by 0 in
software.

Who said anything about *the compiler* doing something? The
claim I made -- and stand by -- is that *the implementation* made
a check for division by zero, detected it, and took action. It
matters not one whit whether the check is done by hardware, or by
a division subroutine (lots of machines nowadays have no integer
divide instruction), or by the equivalent of

if (divisor == 0) abort();
quotient = dividend / divisor;

The check is made, somehow, on every *implementation* I've seen in
three and a half decades of using C. C does not require the check
("undefined behavior" is all), but every implementation of C and
every implementation of every other language I've ever used has made
some kind of zero-division check and handled it as a special case.
Hardware, software, firmware, vaporware, somehow a check is made.
If so then in my opinion this is a deficiency in the definition of C.
Passing a NULL pointer to free should yield an undefined behavior in my
opinion.

Submit a bug report to the Committee, then.
 
M

Moi

Tim Harig said:
On 2010-05-20, bart.c <[email protected]> wrote:

Huh? Where does it say that ?: is associated with assignments? ?: is
used just like any other operator, while indentation might be used like
this (imagine a,b,c are more complex than they are).:

p->q->r = a
?b
:c


Notice that r is being assigned a value here. My point was, what if
there is no assignment being made? The code just branches to do
different tasks. The code below was designed as an example.


A pattern where the ?: can be used as a pure expression
(without using it an assignment) is:

switch (p? p->status : -1) {
case -1:
...
break;
case STATUS_OUT_OF_PAPER:
...
break;
case FILE_NOT_FOUND:
...
break;
case WATER_IN_DRIVE_A:
start_pumping();
break;
....
}

Similar uses can be constructed with if(), for() and while(),
but there a short circuit evaluation is probably more readable.
(and more common idiom)

HTH,
AvK
 
B

BruceS

It allows you to write cleaner code:

  p = malloc (...);
  q = malloc (...);
  r = malloc (...);
  s = malloc (...);

  if (p && q && r && s) {
    /* ok */
  } else {
    /* error */
  }

  free (p);
  free (q);
  free (r);
  free (s);

The cleanup would be a lot bulkier (to me) if I had to
add an if() statement before every free().

This is where I'd do it quite differently, more like:

char *p = malloc(...);
if ( !p )
/* error */
else
{
int *q = malloc(...);
if ( !q )
/* error */
else
{
mystruct *r = malloc(...);
if ( !r )
/* error */
else
{
char *s = malloc(...);
if ( !s )
/* error */
else
{
/* ok */
free(s);
} //allocated s
free(r);
} //allocated r
free(q);
} //allocated q
free(p);
} //allocated p

To me, the beauty of free(NULL) being guaranteed to work (for some
definition of "work") is that either of us can understand the other
approach, and know what it's doing. I generally avoid freeing NULL
pointers, just as I generally avoid multiple returns from a function,
but recognize this as a style preference, not a holy command. My
objection to your approach is more that you don't know which
allocation failed (it may be pointless to differentiate), not that
there's anything "sloppy" or "wrong" with it.
I wish fclose(NULL) had the same semantics as free(NULL),
but unfortunately it doesn't. I try to always follow the
free(NULL) pattern when I write code that allocates/frees
some kind of resource. There's nothing sloppy about it.
It's just the cleanest and most obvious way to do it (in
my mind).

I agree about fclose(). I would be very unlikely to use that feature,
but to my way of thinking it would still be a better interface if it
worked that way. Then again, I'd also prefer an fclose() that NULLed
the FILE * [i.e. fclose(&myfileptr); ], and a free that took a pointer
to the pointer and set it NULL after releasing the memory. Then you'd
only have to be careful of secondary pointers. I could just do

myptr = realloc(myptr, 0);

instead of

free(myptr);
myptr = NULL;

but that seems a bit contrived and "cute", and more likely to confuse
than to communicate.
 
K

Keith Thompson

BruceS said:
I agree about fclose(). I would be very unlikely to use that feature,
but to my way of thinking it would still be a better interface if it
worked that way. Then again, I'd also prefer an fclose() that NULLed
the FILE * [i.e. fclose(&myfileptr); ], and a free that took a pointer
to the pointer and set it NULL after releasing the memory. Then you'd
only have to be careful of secondary pointers. I could just do

myptr = realloc(myptr, 0);

instead of

free(myptr);
myptr = NULL;

but that seems a bit contrived and "cute", and more likely to confuse
than to communicate.

There are two problems with having free() take a pointer-to-pointer
argument. One is that, though void* is a generic pointer type, there is
no generic pointer-to-pointer type. You can't write a myfree() function
for which both of these calls:

int *iptr = malloc(sizeof *iptr);
double *dptr = malloc(sizeof *dptr);
myfree(&iptr);
myfree(&dptr);

are legal.

Second, it doesn't solve the whole problem:

int *p = malloc(sizeof *p);
int *copy_of_p = p;
free(p);
p = NULL;
/* copy_of_p is still a dangling pointer */

Perhaps a partial solution is better than none at all -- but see the
first point.
 
T

Tim Harig

Sorry, poor wording. I don't always speak the best English. What I was
referring to is the fact that ?: implies an assignment (ie, the first
argument).
At first, I thought you were young and naive regarding programming.

I wish I was young :(
I was wrong - you're simply full of crap. No :? ever implies that
a value is changing. Please put down the crack pipe.

Would a crack pipe help diminish my growing gut? Where can I get one! :)
 
T

Tim Harig

A pattern where the ?: can be used as a pure expression
(without using it an assignment) is:

switch (p? p->status : -1) {
case -1:
...
break;
case STATUS_OUT_OF_PAPER:
...
break;
case FILE_NOT_FOUND:
...
break;
case WATER_IN_DRIVE_A:
start_pumping();
break;
...
}

Okay, assignment isn't the proper word. A value is still being returned
here and it is still being used; it just isn't being assigned to a varable.

My question would be why p hasn't already been checked against a NULL
condition? One would that that this would be done when it was first
allocated; before one would assume any of its contents would have any
sanity. Notice that this isn't all that descriptive either. Your testing
two non-dependant condtions at the same time. This alone raises a flag in
my mind.
 
W

Willem

BruceS wrote:
) I agree about fclose(). I would be very unlikely to use that feature,
) but to my way of thinking it would still be a better interface if it
) worked that way. Then again, I'd also prefer an fclose() that NULLed
) the FILE * [i.e. fclose(&myfileptr); ], and a free that took a pointer
) to the pointer and set it NULL after releasing the memory. Then you'd
) only have to be careful of secondary pointers. I could just do
)
) myptr = realloc(myptr, 0);
)
) instead of
)
) free(myptr);
) myptr = NULL;
)
) but that seems a bit contrived and "cute", and more likely to confuse
) than to communicate.

How about making free() always return NULL ?

Then you can simply do: myptr = free(myptr);
Which is nicely parallel to the realloc() version.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
M

Moi

Sorry, poor wording. I don't always speak the best English. What I was
referring to is the fact that ?: implies an assignment (ie, the first
argument).

No, this is not a fact.
See may orher post with
"switch (p ? p->status : -1 ) { ...}"
No assignment.

HTH,
AvK
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top