Proper way to check malloc return

A

andy_P

That's exactly what I said in my previous post. Standard defines
conversion from 0 to null pointer, but not backwards - from null
pointer to integral type. if(ptr) construct implies implicit
conversion from ptr to integral type. 6.3.2.3.(6) states that ptr to
integral type conversion is implementation dependent.

I am still convinced that pointer comparison should be used in C
instead of if(ptr) form.
 
A

andy_P

OK. I've got it.

if(ptr) implies if(ptr != (void*)0). It really does not matter which
form to use.

Thank you.
 
T

Tom St Denis

7.20.4.3 "The exit function", p1: "void exit(int status);"

6.5.13 "Logical AND operator", p2: "Each of the operands shall have scalar
type."

6.2.5 "Types", p18: "Integer and floating types are collectively called
arithmetic types", p21: "Arithmetic types and pointer types are
collectively called scalar types".

(pointer = malloc(number))
|| (fprintf(stderr, "An error!\n"), (exit(1), 0));

That's also missing the possibility that fprintf returns zero
therefore in the original && case does nothing to exit.

It's also really stupid way to code. I'd accept the

if ((a=b) == NULL) { ... }

snippet any day over abusing || and &&.

Tom
 
K

Keith Thompson

Richard Heathfield said:

No, he's right.

Conversion of a constant expression 0 to void* does yield a null
pointer. (Conversion of a non-constant integer expression with the
value 0 doesn't necessarily yield a null pointer, but he didn't
mention that). Conversion of a null pointer to an integer type
yields an implementation-defined result.

<OT>
In C, a null pointer constant is a integer constant expression with the
value 0, or such an expression cast to void*. C++ doesn't have the
"cast to void*" case.
</OT>
 
K

Keith Thompson

andy_P said:
That's exactly what I said in my previous post. Standard defines
conversion from 0 to null pointer, but not backwards - from null
pointer to integral type. if(ptr) construct implies implicit
conversion from ptr to integral type. 6.3.2.3.(6) states that ptr to
integral type conversion is implementation dependent.

I am still convinced that pointer comparison should be used in C
instead of if(ptr) form.

Please don't top-post. New text should *follow* the quoted text
to which it's a response. See:
http://www.caliburn.nl/topposting.html
http://www.cpax.org.uk/prg/writings/topposting.php

I also prefer "if (ptr != NULL)" over "if (ptr)", but only for
stylistic reasons; both mean exactly the same thing.

"if (ptr)" doesn't imply an implicit conversion from pointer
to integer. The expression in an if statement (or in any other
context requiring a condition) merely has to be of scalar type.
It's not implicitly converted, it's implicitly compared to zero.
In the case if "if (ptr)", that's equivalent to "if (ptr != 0)";
the constant 0 is converted to the pointer type, and the result is
well defined. See C99 6.8.4.1 and 6.5.9.
 
S

Seebs

You'd better check against NULL since C std states that malloc should
return NULL if allocation attempt fails.

He did.
NUL is not always defined as 0 (not for all systems)

NUL is a different thing than NULL. NUL is an ASCII character code which
is always 0. NULL is a null pointer constant.
So, if you want your code to be portable you'd better check against
NULL.

Actually, this is unnecessary. If you write
(p == 0)
where p is a pointer type, the 0 is converted automatically to pointer type,
and the conversion produces a null pointer, so this is guaranteed to be a
working test for a null pointer. If you write
(!p)
you are implicitly comparing against 0, and the same applies.

-s
 
S

Seebs

I am still convinced that pointer comparison should be used in C
instead of if(ptr) form.

You're still wrong. if (ptr) is absolutely guaranteed to execute its code
if ptr is not null, and not to execute that code if ptr is null.

-s
 
K

Keith Thompson

Seebs said:
He did.


NUL is a different thing than NULL. NUL is an ASCII character code which
is always 0. NULL is a null pointer constant.

Another difference is that the identifier NUL is not defined in C.
It's the conventional name for the ASCII null character, but
no standard C header defines the name NUL. (If you want a null
character, just write '\0'.)

[...]
 
M

Malcolm McLean

I also prefer "if (ptr != NULL)" over "if (ptr)", but only for
stylistic reasons; both mean exactly the same thing.
The capitailised identifier shouts? Why would you give it that sort of
emphasis?
 
K

Keith Thompson

Malcolm McLean said:
The capitailised identifier shouts? Why would you give it that sort of
emphasis?

Um, you do know that capitalizing NULL wasn't my idea, don't you?
 
K

Keith Thompson

If that statement is for stylistic reasons, you are entitled to your
opinion.

If that statement is for alleged portability reasons, you are wrong.
Any compiler that gets that wrong is so broken you will have a lot of
problems compiling existing code.

I'd say that any compiler that gets that wrong is not a C compiler,
and you're not likely to find it unless you're in the early stages
of implementing it yourself.
The C standard does not require a null pointer to be represented
as the bit pattern 0xdeadbeef, even on 32-bit machines, nor does
it require a null pointer to be represented as 0xdeadbeefdeadbeef
on 64-bit machines. However, if it does have that 32-bit representation,
all 3 sets of code:

if (ptr) { ... }
and
if (ptr != 0) { ... }
and
if (ptr != NULL) { ... }

may all generate the same code, which might be: [snip]
In any case, a good compiler will generate identical code for all three
code fragments. The behavior of the C code does *NOT* depend on whether
the internal representation of a null pointer is or isn't all-bits-zero.

Ah, but his argument wasn't based on the representation of a null
pointer, it was based on the assumption that "if (ptr)" performs
an implicit conversion of ptr to some integral type. If that
assumption were correct, he'd be correct, since the result of such
a conversion is implementation-defined. But the assumption was
incorrect, as I explained a while ago; "if (ptr)" compares ptr to
0, which results in 0 being converted to the pointer type, which
is a well defined operation.

[As always, permission to quote my Usenet postings is granted if
and only if they are properly attributed.]
 
A

andy_P

I just want to say thank you everyone contributed to this discussion.
Your opinions helped me to get deeper understanding of standard.

Best Regards,
Andy.
 
K

Keith Thompson

Richard Heathfield said:
No, he's right.

No, he's wrong. C++ guarantees that (void *)0 is a null pointer[1],
contrary to his claim. (See ISO/IEC 14882 4.10.) C89 also guarantees
it (see 3.2.2.3).
[snip]

Ok, I'll concede the point.

I think the only error is the phrase "Opposite to C++".

<OT>I'll note that (void*)0, though it yields a null pointer
value in both C and C++, and is a null pointer constant in C,
is not a null pointer constant in C++. But that's not what was
being discussed.</OT>
 
D

David Thompson

Billy Mays wrote:
How would you feel if your word processor did this?
Not all programs are word processors, or more to the point, have
significant interactive input, since some word processing is 'batch'
and some (valuable) interactive input is not of words.

If we count notepad as an interactive editor, and I do:

Once upon an old version of M$Win, I think 2k but am not sure,
I accidentally clicked in Explorer on a file that was nearly a
gigabyte but had a 'type' (extension) associated with notepad.
Which blithely launched and promptly brought my system to a grinding
halt for about an hour. I wasn't able to kill it -- I don't know if it
was formally unkillable, but it took about 5 *minutes* to C-A-del
TaskMan (in whichever incarnation was then applicable), about 10 to
get a mouse selection apparently on the right entry, maybe another 5
for del to get a confirm dialog, and then it apparently did nothing,
possibly because I'd touched the desk in between. And I couldn't power
cycle, because I had other applications up with unsaved data, which I
couldn't focus to do saves or closes! If notepad had just tried malloc
(or similar e.g. ConfusinglyRegionalAlloc) and failed and died, I
would have been hugely better off. Admittedly if it had stat'ed the
file and refused to open it, or at least asked first, that would have
been better yet.

Moral: all generalizations are wrong.
 
D

David Thompson

That's also missing the possibility that fprintf returns zero
therefore in the original && case does nothing to exit.
No. If successful, {,f}printf returns the number of characters output,
which for the literal format here must be 10; if error, it returns
(value of macro) EOF which must be <0 and usually is -1.

sprintf also returns the number output, but never error; C99 snprintf
returns the number *tried to* output even if they were truncated,
although some pre/nonC99 variants return -1 or perhaps <0 for
overflow. The w variants can (also) return <0 for encoding error,
and (C95 IIRC) swprintf returns <0 for overflow.
It's also really stupid way to code. I'd accept the

if ((a=b) == NULL) { ... }

snippet any day over abusing || and &&.
I'm with you there.
 
R

Richard Bos

David Thompson said:
Not all programs are word processors, or more to the point, have
significant interactive input, since some word processing is 'batch'
and some (valuable) interactive input is not of words.

True, but Mr. Mays wrote that he _typically_ reacts to malloc() failure
by crashing. Unless his typical program is a shell filter, that isn't a
desirable habit. It's proper behaviour for a specific kind of programs,
not for a typical program.
If we count notepad as an interactive editor, and I do:

Once upon an old version of M$Win, I think 2k but am not sure,
I accidentally clicked in Explorer on a file that was nearly a
gigabyte but had a 'type' (extension) associated with notepad.
Which blithely launched and promptly brought my system to a grinding
halt for about an hour.

That's odd. IME, there were two versions of Notepad: one which simply
refused to open anything larger than 64k, and one which happily opens
something megabytes large. Yours sounds not like a malloc() failure at
all, but like a very busy read loop after a _successful_ malloc() call.
Not really applicable to the question in this thread, therefore.

Richard
 

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

Forum statistics

Threads
474,091
Messages
2,570,605
Members
47,224
Latest member
Gwen068088

Latest Threads

Top