newbie question on malloc..

Y

Yugi

Is it ok to cast the return value of malloc ?
Because somewhere in this group i read the following...
Do not cast return value of malloc().It's not required, and it masks
failure to include <stdlib.h>.

Could someone explain me this behaviour??
 
N

Neo

malloc() returns a void pointer, pointing to the chunk of memory
captured in heap & suitably typecasting this only ensures an alignment
i.e; every time you increament the pointer or deference it, then intend
to do so by sizeof(casting type) amount.

If malloc fails, then it will definitely return NULL which cann't
be masked.

--Neo
 
E

Eric Sosman

Yugi said:
Is it ok to cast the return value of malloc ?
Because somewhere in this group i read the following...
Do not cast return value of malloc().It's not required, and it masks
failure to include <stdlib.h>.

Could someone explain me this behaviour??

Casting the result of malloc() is permissible in the
sense that it will not break the program (if you do it
correctly). It is also permissible in the sense that you
will not actually be burned at the stake for doing it.

However, it is unnecessary in C programs: malloc()
returns a `void*' value, and this kind of pointer can be
converted to any other kind of data pointer without a cast.
`(char*)malloc(42)' is thus a little bit like `(int)42'
or `(double)3.14159' -- extra clutter that adds nothing
to the program.

The cast can also prevent the compiler from warning
you that you have failed to declare malloc() correctly,
which you ordinarily do by including <stdlib.h>. If you
call a function that has not been declared, the compiler
assumes that the function returns an `int'. This can lead
to trouble because malloc() does not return an `int', and
when the caller tries to retrieve the returned value it may
get the wrong result (e.g., on a machine with 32-bit `int'
and 64-bit `void*'). If you write `char *p = malloc(42);'
the compiler will see that you are trying to assign an `int'
value to a pointer and will issue a diagnostic; this will
(one hopes) remind you to add #include <stdlib.h> to fix the
error.

However, if you write `char *p = (char*)malloc(42);' the
compiler sees that you are *converting* an `int' to a pointer
(an operation that is dubious but permitted) and may not give
any warnings at all. The error will not be detected until
the program misbehaves -- and that might not be until you
port the code to another machine or something. Errors cost
more the longer they sit undetected in the code, so silencing
the warning increases your development and support costs.

Some compilers will warn about the use of an undeclared
function, cast or no cast, if their warning sensitivity is
turned up high enough. It is an excellent idea to operate
your compiler in such a mode, if it has one. Also, the latest
"C99" Standard *requires* a diagnostic for the use of undeclared
functions, so the problem may fade away as C99 compilers become
more widespread (which is taking a l-o-n-g time; don't hold
your breath).

Finally, casting the result of malloc() is *mandatory* in
a C++ program, because the rules of C++ are different from
those of C. In "pure C++" code you probably shouldn't use
malloc() very much anyhow; C++ has other ways to manage memory.
But if you are writing code that (for some strange reason) must
have a "dual personality" and work both as C and C++, you will
need to cast the result of malloc() -- and suffer the scorn of
both the C and C++ communities.
 
F

Flash Gordon

Neo wrote:

Please provide context when replying. See 99% of the posts in the group!
malloc() returns a void pointer, pointing to the chunk of memory
captured in heap & suitably typecasting this only ensures an alignment

No it doesn't. Firstly, the pointer returned by malloc is guaranteed to
be suitable aligned to point to any type of object. Secondly, casting a
pointer does not ensure *anything* about the alignment.
i.e; every time you increament the pointer or deference it, then intend
to do so by sizeof(casting type) amount.

If malloc fails, then it will definitely return NULL which cann't
be masked.

Why would you want to mask it?

If you want to know about casting malloc, start off by reading the
comp.lang.c FAQ. Casting the result of malloc is *not* required in C,
and if you forget to include stdlib.h it can suppress a diagnostic that
the compiler is otherwise *required* to produce.
 
W

websnarf

Yugi said:
Is it ok to cast the return value of malloc ?
Because somewhere in this group i read the following...
Do not cast return value of malloc().It's not required, and it masks
failure to include <stdlib.h>.

Could someone explain me this behaviour??

You mean the behaviour of the poster? The reason why that poster,
whichever one it was, says that is because he doesn't care about real
world programming, but instead cares about a very particular narrow
dogma that doesn't really apply anymore.

Its kind of like using the "register" keyword. Once upon a time,
compilers optimized better if you put that keyword in your program.
Nowadays, performance is just a function of the optimizer and
brainpower. Similarly, some old C compilers perhaps may just plop in
an assumed int (*)() prototype for &malloc without a warning.
Certainly no modern C compiler does that -- you will get the warning,
regardless of the cast.

And of course, in the real world, people often want/need to write C
code which can be compiled straight in a C++ compiler. In this case,
you *have* to perform the cast anyways. That's not a consideration
that poster would ever consider.

The way I look at it is, using "void *" for anything basically removes
type checking, and so it should be avoided at all costs. In the case
of malloc, you can't really do that, but you can at least *document*
what your intention is. The cast basically does this.
 
S

Simon Biber

Neo said:
malloc() returns a void pointer, pointing to the chunk of memory
captured in heap

No. There is no such thing as a heap in C. Your implementation may or
may not have a single block of memory from which it allocates chunks,
may or may not call it a heap, and may or may not use a heap data structure.
& suitably typecasting this only ensures an alignment
i.e; every time you increament the pointer or deference it, then intend
to do so by sizeof(casting type) amount.

Casting the void* to the target type has nothing to do with alignment.
The conversion will occur the same whether you cast it or not.

The cast is a throwback to the days before there was such a thing as
void*, when malloc returned char*, and a cast was required to convert it
to the correct type.

If you get an error when trying to compile code that doesn't cast the
result of malloc, you are probably trying to compile your code as C++.
In that case, you should really be using new and delete rather than
malloc and free.
If malloc fails, then it will definitely return NULL which cann't
be masked.

If you called malloc without a valid prototype, ie. you did not include
<stdlib.h>, then the compiler will assume that malloc returns an int.
This causes undefined behaviour since malloc actually returns a void*.
The return values for int and void* may be stored in different registers
or in different parts of memory. The types int and void* may be of
different sizes (32-bit int and 64-bit void* is quite common nowadays).
It is quite likely that you will not get the correct value back from malloc.

This includes the value of the null pointer, which may be mangled or
incorrect after being returned through a wrongly prototyped function.
 
S

Simon Biber

Its kind of like using the "register" keyword. Once upon a time,
compilers optimized better if you put that keyword in your program.
Nowadays, performance is just a function of the optimizer and
brainpower. Similarly, some old C compilers perhaps may just plop in
an assumed int (*)() prototype for &malloc without a warning.
Certainly no modern C compiler does that -- you will get the warning,
regardless of the cast.

You often don't get a warning:

C:\docs\prog\c>type NoCast.c
int main(void)
{
int *p = malloc(10);
return 0;
}

C:\docs\prog\c>gcc NoCast.c

C:\docs\prog\c>gcc -ansi -pedantic NoCast.c

Neither of these invocations of GCC gave me any warning that I failed to
include <stdlib.h>. It's only if I ask GCC to give me warnings that it
does so:

C:\docs\prog\c>gcc -Wall NoCast.c
NoCast.c: In function `main':
NoCast.c:3: warning: implicit declaration of function `malloc'

Even here, the warning was about the implicit declaration of the
function, not about the conversion from int to int* without a cast.

If I go back and add the cast to (int *), and recompile with each of the
3 sets of compiler flags as above, the results are exactly the same in
each case.

When compiling with GCC, we can see there is no change from putting in
or leaving out the cast.

However, if I try compiling with Microsoft's compiler, the results are a
different story. When there is no cast, I get the warning:

NoCast.c(3) : warning C4047: 'initializing' : 'int *' differs in levels
of indirection from 'int'

But when there is a cast, there is no warning at all!

Therefore, with Microsoft's compiler it is worth your while leaving out
the cast, to elicit the warning just in case the <stdlib.h> was not
included.
 
F

Flash Gordon

You mean the behaviour of the poster? The reason why that poster,
whichever one it was, says that is because he doesn't care about real
world programming, but instead cares about a very particular narrow
dogma that doesn't really apply anymore.

Its kind of like using the "register" keyword. Once upon a time,
compilers optimized better if you put that keyword in your program.
Nowadays, performance is just a function of the optimizer and
brainpower. Similarly, some old C compilers perhaps may just plop in
an assumed int (*)() prototype for &malloc without a warning.
Certainly no modern C compiler does that -- you will get the warning,
regardless of the cast.

Or they care about the real world where may compilers will not by
default complain about the lack of prototype, rather than your fantasy
world where everyone uses the latest and greatest version of compilers
even when they are not available for the platform of interest.

markg@markgordon-lp ~
$ gcc --version
gcc (GCC) 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


markg@markgordon-lp ~
$ gcc t.c

markg@markgordon-lp ~
$ cat t.c
int main(void)
{
char *p=(char*)malloc(9);
}

This was only the second compiler I tried, and it is still current under
Cygwin. Of course, it can be made to generate a warning, but people new
to C won't necessarily know how to do that.
And of course, in the real world, people often want/need to write C
code which can be compiled straight in a C++ compiler. In this case,
you *have* to perform the cast anyways. That's not a consideration
that poster would ever consider.

I've only seen one person that has managed to come of with a decent
justification for them doing it, and that justification does not apply
to others. C++ provides a perfectly good mechanism for calling C code
without the need to make the C code valid C++, and I've yet to see a
situation where a C compiler was not provided with the C++ compiler.
The way I look at it is, using "void *" for anything basically removes
type checking, and so it should be avoided at all costs.

No, it should be used where ever it is appropriate.
> In the case
of malloc, you can't really do that, but you can at least *document*
what your intention is. The cast basically does this.

Assigning it to a pointer variable of the appropriate type documents
that you want it to be that type. Not using a cast also reduces needless
clutter making the code easier to read and reduces how often information
is repeated making maintenance easier.
 
D

Default User

Yugi said:
Is it ok to cast the return value of malloc ?
Because somewhere in this group i read the following...
Do not cast return value of malloc().It's not required, and it masks
failure to include <stdlib.h>.

Could someone explain me this behaviour??

I just answered the same damn question yesterday. Try to read the
newsgroup BEFORE you post.

http://c-faq.com/malloc/decl.html
http://c-faq.com/malloc/mallocnocast.html

Read the rest of the FAQ list as well.




Brian
 
W

websnarf

Simon said:
You often don't get a warning:

C:\docs\prog\c>type NoCast.c
int main(void)
{
int *p = malloc(10);
return 0;
}

C:\docs\prog\c>gcc NoCast.c

C:\docs\prog\c>gcc -ansi -pedantic NoCast.c

Neither of these invocations of GCC gave me any warning that I failed to
include <stdlib.h>.

I.e., when you don't ask for warnings, you don't get any. I follow you
so far.
[...] It's only if I ask GCC to give me warnings that it
does so:

Really? What a shocker. (Not asking for or ignoring warnings is not a
sustainable way of programming, BTW.)
C:\docs\prog\c>gcc -Wall NoCast.c
NoCast.c: In function `main':
NoCast.c:3: warning: implicit declaration of function `malloc'

Even here, the warning was about the implicit declaration of the
function, not about the conversion from int to int* without a cast.

That's because the real bug is the lack of the declaration which may be
perpetrating the other warning (which thus becomes redundant.)
If I go back and add the cast to (int *), and recompile with each of the
3 sets of compiler flags as above, the results are exactly the same in
each case.

Right. Now go back and replace the cast with (double *) and tell me
what you get. That's the real point.
When compiling with GCC, we can see there is no change from putting in
or leaving out the cast.

Which doesn't support the point for removing the cast.
However, if I try compiling with Microsoft's compiler, the results are a
different story. When there is no cast, I get the warning:

NoCast.c(3) : warning C4047: 'initializing' : 'int *' differs in levels
of indirection from 'int'

Microsoft choses not to calculate shadowed warnings. Its not a big
deal. The resolution is still the same; remember to include said:
But when there is a cast, there is no warning at all!

I was not able to reproduce this with MSVC even with /W1. So I don't
know what you are talking about. Watcom required /w3, and Intel
required a /W3. Borland issues the warning without any warning switch
requested. As soon as you ask for sufficient warnings from any
compiler, you will get the warning you need to avoid this problem.
 

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

Similar Threads

malloc and maximum size 56
Malloc question 9
malloc 40
Question regarding malloc casing 10
[C#] Extend main interface on child level 0
MALLOC problem 25
malloc() and implicit cast 49
malloc and alignment question 8

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top