malloc questions

J

Jack

The code is below:

char *p;
p = (char*)malloc(10 * sizeof(char)); //LINE1

After LINE1, the 10 char-length memory that p points to is empty or
some random characters?

Thanks.
 
R

Richard Heathfield

Jack said:
The code is below:

char *p;
p = (char*)malloc(10 * sizeof(char)); //LINE1

Better: p = malloc(10 * sizeof *p);
After LINE1, the 10 char-length memory that p points to is empty or
some random characters?

The values of the ten bytes, starting with the byte pointed to by p, are
indeterminate. That means you can't rely on their having meaningful values.

I am reluctant to accede to the use of the word "random", in case it gives
you the idea that you can get entropy from those bytes. You certainly can't
do that reliably.

The safe, portable assumption to make is that you must not /read/ from those
bytes unless you have first /written/ values to them.
 
T

Tomás

Jack posted:
The code is below:

char *p;
p = (char*)malloc(10 * sizeof(char)); //LINE1

After LINE1, the 10 char-length memory that p points to is empty or
some random characters?


Random characters -- and you've no guarantee that there's a terminating
null character, so don't do the following:

char * const p = malloc(10);

printf("%s", p);


"calloc" on the other hand will set all bits to zero.

If you want to dynamically allocate an array of doubles, or perhaps an
array of pointers, you'll have to manually set each element to zero:

#include <...

int main(void)
{
enum { len = 45 };

double *p = malloc( sizeof( double[len] ) );


const double * const p_over = p + len;

do
{
*p++ = 0;
} while ( p != p_over );

}


I suppose you could make a function for creating an array of objects with
"default" values:


typedef char T;

T * const allocdef( unsigned const amount_elem )
{
T * const p = malloc( sizeof( T[amount_elem] ) );

const T * const p_over = p + amount_elem;

do
{
*p++ = 0;
} while ( p != p_over );
}


-Tomás
 
G

Gordon Burditt

char *p;
p = (char*)malloc(10 * sizeof(char)); //LINE1

After LINE1, the 10 char-length memory that p points to is empty or
some random characters?

memory is never "empty".

There is no guarantee what is in the memory you malloc() and you
shouldn't read it until you've put something in it. It is certainly
not guaranteed to contain cryptographically-secure random numbers,
nor is it guaranteed to be initialized to all-bits 0xdeadbeef.
"garbage" is probably a better description. If you want it initialized
to all-bits-zero, use calloc().

Gordon L. Burditt
 
R

Richard Bos

Jack said:
char *p;
p = (char*)malloc(10 * sizeof(char)); //LINE1

This is not the best way to call malloc().

First, if you have a proper prototype in scope, the cast does nothing.
OTOH, if you do not have a proper prototype in scope, the cast is likely
to hide any error messages your compiler might have given you to warn
you of this mistake, and the result is likely to be garbage. Lose the
cast.
Second, sizeof(char) is always 1. This is guaranteed by the Standard. If
you know that p is always going to be a char * (i.e., it holds a
string), you can omit the sizeof(char).
OTOH, if you do _not_ know that p is always going to be a char * (e.g.,
it holds flags, and it may some day become a struct flags * instead),
then it should be treated as a normal malloc() call. Any normal malloc()
call is easier to maintain properly if you do not ask for N*sizeof(type)
but for N*sizeof *pointer. When the type of the pointer changes,
N*sizeof(type) may be incorrect and need changing; but N*sizeof *pointer
is always right no matter what type pointer has.
Also, double spacing is an abomination concocted by a conspiracy of
typewriter makers and stationers. Also also, magic numbers are to be
abhorred.

All in all, your code is better this way:

#define MAX_LENGTH 10

char *p;
p = malloc(MAX_LENGTH * sizeof *p);

After LINE1, the 10 char-length memory that p points to is empty or
some random characters?

The latter.

Richard
 
S

Simon Biber

Tomás said:
I suppose you could make a function for creating an array of objects with
"default" values:


typedef char T;

T * const allocdef( unsigned const amount_elem )
{
T * const p = malloc( sizeof( T[amount_elem] ) );

The line above defines p is a const variable pointing at non-const data.
You cannot modify p, but you may modify *p. The operand of sizeof is a
variable-length array type, which is valid in C99 but not in C89. You
should check whether malloc returned NULL.
const T * const p_over = p + amount_elem;

p_over is a const variable pointing at const data. You can neither
modify p_over or *p_over.
do
{
*p++ = 0;

The line above attempts to modify both p and *p. That is not allowed, as
p is const. The compiler should diagnose this error.
} while ( p != p_over );

You failed to return a value from this function. It would be unusual to
return p at this point, as it points one element past the end of the
allocated buffer.
}


-Tom嫳

That's an interesting Chinese character in your name. It's there because
you didn't include a Content-type header in your post. Your news client
should be configured to put:

Content-Type: text/plain; charset="iso-8859-1"

Otherwise, news readers have no way to tell what encoding you really
intended. My one erroneously detected Big5, a legacy encoding for
traditional Chinese characters.

In my opinion it's bad form to post non-ASCII characters to newsgroups
without a valid Content-type header.
 
H

Haider

Richard said:
This is not the best way to call malloc().

First, if you have a proper prototype in scope, the cast does nothing.
OTOH, if you do not have a proper prototype in scope, the cast is likely
to hide any error messages your compiler might have given you to warn
you of this mistake, and the result is likely to be garbage. Lose the
cast.
Second, sizeof(char) is always 1. This is guaranteed by the Standard. If
you know that p is always going to be a char * (i.e., it holds a
string), you can omit the sizeof(char).
OTOH, if you do _not_ know that p is always going to be a char * (e.g.,
it holds flags, and it may some day become a struct flags * instead),
then it should be treated as a normal malloc() call. Any normal malloc()
call is easier to maintain properly if you do not ask for N*sizeof(type)
but for N*sizeof *pointer. When the type of the pointer changes,
N*sizeof(type) may be incorrect and need changing; but N*sizeof *pointer
is always right no matter what type pointer has.
Also, double spacing is an abomination concocted by a conspiracy of
typewriter makers and stationers. Also also, magic numbers are to be
abhorred.

All in all, your code is better this way:

#define MAX_LENGTH 10

char *p;
p = malloc(MAX_LENGTH * sizeof *p);
above lines of code gives compilation error on MS VC++ 6.0
so i think cast has to be there
 
V

Vladimir Oka

Haider said:
above lines of code gives compilation error on MS VC++ 6.0
so i think cast has to be there

Try using it in C mode.

Cast is only required in C++ (even then, you'd probably really want to
use `new`).
 
C

Chris Dollin

Haider said:
above lines of code gives compilation error on MS VC++ 6.0
so i think cast has to be there

Why are you compiling /C/ code with a /C++/ compiler? Use a C
compiler.

(Or write idiomatic malloc-free C++.)
 
H

Haider

Chris said:
Why are you compiling /C/ code with a /C++/ compiler? Use a C
compiler.

(Or write idiomatic malloc-free C++.)
MS VC++ claims to compile and build C file. anyway I used option to
compile in C mode only and it works it rejects C++ keyword such as
class, private etc. but still it gives error. on malloc without
casting.
 
R

Richard Bos

Haider said:
MS VC++ claims to compile and build C file.

If MS VC++ claims to compile C, but refuses to compile the lines above,
MS VC++ is lying about compiling C.
anyway I used option to compile in C mode only and it works it
rejects C++ keyword such as class, private etc. but still it
gives error. on malloc without casting.

Then a. you should look this up in the Standard if you don't believe us
and b. you should get a compiler that isn't broken.

Richard
 
H

Haider

Richard said:
[ Snip! ]
above lines of code gives compilation error on MS VC++ 6.0

Use a real C compiler, then, not a pink-elephant compiler forced to work
on C code.
so i think cast has to be there

You think wrongly.
I have gone through the C Programming by K&R and found that where ever
they used malloc they typecast to appropriate so atleast it is good
practice to use cast and code will be more portable too.
 
R

Richard Tobin

Haider said:
MS VC++ claims to compile and build C file. anyway I used option to
compile in C mode only and it works it rejects C++ keyword such as
class, private etc. but still it gives error. on malloc without
casting.

What error does it give? Have you read the error message and
understood it? It doesn't by any chance say something about
converting int to char * does it? You have remembered to include
the header that declares malloc(), haven't you?

Anyway, I'm sure that there are thousands of C programs that have been
successfully compiled with that compiler without changing the code, so
there is sure to be some way of making it accept standard C. Try
asking on a Microsoft newsgroup.


-- Richard
 
T

Tim Prince

Richard said:
If MS VC++ claims to compile C, but refuses to compile the lines above,
MS VC++ is lying about compiling C.


Then a. you should look this up in the Standard if you don't believe us
and b. you should get a compiler that isn't broken.

Richard
Microsoft docs say succinctly what was snipped from Richard's reply
above about "prototype in scope":
_______________________________________________________
void *malloc( size_t size );

Routine Required Header Compatibility
malloc <stdlib.h> and <malloc.h> ANSI, Win 95, Win NT
________________________________________________________
If you fail to include the standard or pre-standard header, you don't
have what you call "C file," and the compiler is certainly entitled to
adverse reaction.

#include <stdlib.h>
#define MAX_LENGTH 10
int main(){
char *p;
p = malloc(MAX_LENGTH * sizeof *p);
}

No complaint from CL.
 
T

Tim Prince

Haider said:
Richard said:
[ Snip! ]
Richard Bos wrote:

char *p;
p = (char*)malloc(10 * sizeof(char)); //LINE1
This is not the best way to call malloc().

First, if you have a proper prototype in scope, the cast does nothing.
OTOH, if you do not have a proper prototype in scope, the cast is likely
to hide any error messages your compiler might have given you to warn
you of this mistake, and the result is likely to be garbage. Lose the
cast.
char *p;
p = malloc(MAX_LENGTH * sizeof *p);
above lines of code gives compilation error on MS VC++ 6.0
Use a real C compiler, then, not a pink-elephant compiler forced to work
on C code.
so i think cast has to be there
You think wrongly.
I have gone through the C Programming by K&R and found that where ever
they used malloc they typecast to appropriate so atleast it is good
practice to use cast and code will be more portable too.

Then why do Microsoft docs say it is __mandatory__ to use <malloc.h> if
you reject C89? My 15 year old copy of H&S points out explicitly how
your recommendation will fail on some of the platforms from the pre-89 era.
Going back a little further, my Unix V7 manual says the following is
required:
char * malloc(size)
unsigned size

As your claim to better portability appears to be based on going back
before 1989, you might consider some of the relevant reference material.
 
H

Haider

Richard said:
What error does it give? Have you read the error message and
understood it? It doesn't by any chance say something about
converting int to char * does it? You have remembered to include
the header that declares malloc(), haven't you?

Anyway, I'm sure that there are thousands of C programs that have been
successfully compiled with that compiler without changing the code, so
there is sure to be some way of making it accept standard C. Try
asking on a Microsoft newsgroup.
Thanks it works MS VC++ is not giving error with malloc without casting
I again check the compiler setting and give an explicit compiler option
to compile for C only and it works
Thanks once again to you all for removing my confusion.

Haider.
 
C

Chris Dollin

Haider said:
I have gone through the C Programming by K&R and found that where ever
they used malloc they typecast to appropriate so atleast it is good
practice to use cast and code will be more portable too.

I googled "C programming language second edition errata" and the top hit
was:

http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html

which says:

142(§6.5, toward the end): The remark about casting the return value of malloc
("the proper method is to declare ... then explicitly coerce") needs to be rewritten.
The example is correct and works, but the advice is debatable in the context of the
1988-1989 ANSI/ISO standards. It's not necessary (given that coercion of void *
to ALMOSTANYTYPE * is automatic), and possibly harmful if malloc, or a proxy for it,
fails to be declared as returning void *. The explicit cast can cover up an unintended error.
On the other hand, pre-ANSI, the cast was necessary, and it is in C++ also.

You don't need it (in C), it doesn't do anything, and it can conceal a genuine
portability problem. I don't think it's "good practice" (although there may be
good /local/ reasons for doing it), and the additional portability it provides
is ... suspect.
 
F

Flash Gordon

Richard said:
If MS VC++ claims to compile C, but refuses to compile the lines above,
MS VC++ is lying about compiling C.

I've got lots of code that uses implicit conversion from void* (malloc
is wrapped in a function that returns void*) and don't get complaints
about it.
Then a. you should look this up in the Standard if you don't believe us
and b. you should get a compiler that isn't broken.

It isn't, at least not in that respect. Haider needs to look more
carefully at what compiler options are being used or ask on a MSVC group.
 

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
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top