473,383 Members | 1,803 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,383 software developers and data experts.

IS this a proper way of freeing memory with free()

Hi All,

Here is a small Code,

int main(void)
{
char *p=(char *) malloc(100);
strcpy(p,"Test1234567890");
p=p+10;
free(p);
/*** Is here a memory Leak, because p is now
pointing 10 location past to the start of allocated memory
****/

/** some stuff with p again**/


}
Thanks and Regards,
Raman Chalotra

Feb 1 '07
171 4698
Richard Heathfield wrote:
Yevgen Muntyan said:
>Richard Heathfield wrote:
>>Yevgen Muntyan said:
<snip>
>>>But I still believe that

#define ALLOC_A_THING(Type) ((Type*) malloc (sizeof (Type)))

is not too bad.
It's ghastly. It doesn't buy you anything useful. It doesn't
encapsulate anything worth encapsulating.
#define ALLOC_A_THING(Type) ((Type*) custom_allocator_here (sizeof
#(Type)))

Even with malloc this macro is more convenient than malloc(sizeof
*foo) or malloc(sizeof(Foo)) (given the name is better than
"custom_allocator_here").

I fail to see why:

p = ALLOC_A_THING(foo);

is more convenient than:

p = malloc(sizeof *p);
You fail to see, I don't. I like ALLOC_A_THING because
it describes the intent and hides the actual memory
allocation. Anyway, let it be not convenient. How
about custom_allocator_here() function?

Here's real code example.

MooClosure *moo_closure_alloc (gsize size,
MooClosureCall call,
MooClosureDestroy destroy);
#define moo_closure_new(Type__,call__,destroy__) \
((Type__*)moo_closure_alloc (sizeof(Type__), call__, destroy__))

Equivalent effect if moo_closure_alloc returns void*.
>Or

#define FOO_NEW() ((Foo*) malloc (sizeof (Foo))) // *must* cast here

Why? The cast doesn't do any good,
It saves your butt if you change type, the famous "why you shall do
malloc(sizeof *ptr)" thing, you know.
and in any case this is a lousy way
to create an object of a particular type. You'd be far better off with
a function that could not only reserve storage for the object but also
populate it with its initial value.
Sure, malloc() there is silly. Custom allocation function which does
more than calling malloc is much more realistic. See the above macro.
Now you can tell it's possible to avoid anything of that sort. Of
course it is.

Yevgen
Feb 9 '07 #101
Mark McIntyre wrote:
On Thu, 08 Feb 2007 13:14:44 -0600, in comp.lang.c , Yevgen Muntyan
<mu****************@tamu.eduwrote:

Flash wrote
>>1) In C++ there are better methods than using malloc to get memory
>You lose compatibility with C then ;)

Yes, people who think C and C++ are compatible often do seem to prefer
sloppy ill-defined compatibility over formal but slightly harder to
use compatibility. Smiley noted.
It's easy to write lot of C code which is valid C++. You have to
apply casts to return value of malloc though.
>>2) C++ defines mechanisms to interface to C code that has been compiled
as C code.
>And I am talking about compiling *C* code with *C++* compiler.

If you're compiling it with a C++ compiler, its C++ code. It may look
like C, it may also compile as C, but its C++, and probably badly
written C++ at that.
Okay, let's use this term: "C code which is intended to be compiled
both with C and C++ compilers". I mean "C code" by "C code", i.e.
the code which is C according to C standard and is compilable with
C compiler in conforming mode. Not sure it's strict enough, but hope
you get the idea (which you already got anyway, I believe).
And no, C code doesn't become C++ code because you feed it to g++, even
if C++ folks think it is :)

Regards,
Yevgen
Feb 9 '07 #102
Mark McIntyre wrote:
On Thu, 08 Feb 2007 12:56:40 -0600, in comp.lang.c , Yevgen Muntyan
<mu****************@tamu.eduwrote:
>Mark McIntyre wrote:
>>On Thu, 08 Feb 2007 01:36:11 GMT, in comp.lang.c , Yevgen Muntyan
<mu****************@tamu.eduwrote:
Me: I am fine here, I make gcc take care of this.
You: No, you're wrong. anycc is not obliged to emit a warning.
Me: *I* make *gcc* take care of this *here*.
You: No, you're wrong. See above.
You: its ok, I always put the safety on.
Me: its still dangerous, safetys don't always work.
You: *I* always make sure the safety is *on*. So there.
Me: I wouldn't do -
<sfx>*BANG* </>
You: urk.
Me: oh well, Darwin in action.
Indeed, code tends to break when you don't touch it.

I assume you got the point, and are merely trying to avoid it. :-)
>You put cast in, it explodes in two months.

Sure, if during that 2 months, you upgraded your compiler, OS or
target infrastructure.
You mean you upgrade compiler or OS and it breaks valid correct
code? It will break valid code without cast as well. I am sure
it's not what you meant. You were talking about habits here,
like if I'm used to gcc producing warning and rely on that,
it will beat me. This is certainly true, and I don't cast return
value of malloc if I don't need to. Still, existing cast
in valid correct code is *not* a problem.

But when some person says "it's not a problem", he gets a laconic
response "Wrong.", the response from a person who didn't try hard
to understand what he was replying to. And that's the problem.
You get flamed for using potentially harmful construct *without*
any questions. You use it, you're moron. Full stop.
>What you're all saying is why it's not a good idea to
use cast. And that's indeed true, it's not a good idea
to cast when you don't have to.

And malloc is a case where you don't have to.
Not always. But yes, usually casting return value of malloc
is not a good idea.
>What's not true
is that any given piece of code with cast is wrong and
dangerous in any situation.

Nobody ever said that.
Oh yeah people in this thread did say that. That's what the
fuss is about.

Yevgen
Feb 9 '07 #103
CBFalconer wrote:
Yevgen Muntyan wrote:
... snip ...
>What promotes bad habits? Bad habits? Okay, let it be a bad habit
to cast return value of malloc (which I agree with if it's "always
cast"). Do you say that it's fine to claim that the cast in the
following code

#include <stdlib.h>
int main (void)
{
char *foo = (char*) malloc (18);
return 0;
}

*necessarily* and *always* leads to bad results for every single
person in every single situation? Please don't say about habits,
just say "yes" or "no" (and read the thread to see what I am
talking about if you're interested).

Always. He has typed at least eight unnecessary characters,
leading to broken fingernails, various muscular problems, not to
mention the extraneous discussion here and added probability of
spilling coffee (or other liquids) into the keyboard. The program
is also fatally flawed by failure to #include <stdlib.h>, while the
inclusion of stdio.h is totally unnecessary (another 19 excess
chars typed).
Which program is fatally flawed? The one that broke your fingernails?
Or the posted one? Or some other? And who's "he"?

Yevgen
Feb 9 '07 #104
CBFalconer wrote:
matevzb wrote:
... snip ...
>I tend to disagree on this one. If you change the type of "ptr"
you *should* examine *all* the places where "ptr" was used anyhow
(not just the line with malloc). If you don't, that's promoting
bad habits and that may bite harder than the x*sizeof(<type>). I
personally always use the latter and have never had any trouble
with it.

Not necessary. If you have avoided unnecessary casts, the compiler
will point out any harmful type mismatches.
You didn't read what you were replying to, did you?

Yevgen
Feb 9 '07 #105
Yevgen Muntyan <mu****************@tamu.eduwrites:
Mark McIntyre wrote:
[...]
>If you're compiling it with a C++ compiler, its C++ code. It may look
like C, it may also compile as C, but its C++, and probably badly
written C++ at that.

Okay, let's use this term: "C code which is intended to be compiled
both with C and C++ compilers". I mean "C code" by "C code", i.e.
the code which is C according to C standard and is compilable with
C compiler in conforming mode. Not sure it's strict enough, but hope
you get the idea (which you already got anyway, I believe).
And no, C code doesn't become C++ code because you feed it to g++, even
if C++ folks think it is :)
No, C code doesn't become C++ code because you feed it to g++. If g++
accepts it (assuming g++ to be a correctly working C++ compiler), then
it was *already* C++ code.

What you're talking about is code that is simultaneously C code and
C++ code.

I don't want to get too deeply into this argument, but I will say
that, in my opinion, there is rarely a real need to write such code.
(I said "rarely", not "never".)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 9 '07 #106
On Feb 9, 1:11 am, "matevzb" <mate...@gmail.comwrote:
On Feb 8, 11:51 pm, CBFalconer <cbfalco...@yahoo.comwrote:matevzb wrote:
I tend to disagree on this one. If you change the type of "ptr"
you *should* examine *all* the places where "ptr" was used anyhow
(not just the line with malloc). If you don't, that's promoting
bad habits and that may bite harder than the x*sizeof(<type>). I
personally always use the latter and have never had any trouble
with it.
Not necessary. If you have avoided unnecessary casts, the compiler
will point out any harmful type mismatches.

No, it won't in case of void *. A hypothetical case:
#include <stdlib.h>
#include <string.h>

typedef enum
{
SHORT = 0,
LONG = 1
} mytype;

int
fcn (void *array, mytype type, size_t size)
{
void *ptr;

switch (type)
{
case SHORT:
ptr = malloc (size * sizeof(short));
memcpy (ptr, array, size * sizeof(short));
break;

case LONG:
ptr = malloc (size * sizeof(long));
memcpy (ptr, array, size * sizeof(long));
break;

default:
return -1;
}

return 0;
}

int
main (void)
{
long *ptr = malloc (10 * sizeof *ptr);

memset (ptr, 1, 10 * sizeof *ptr);
fcn (ptr, LONG, 10);

return 0;
}

If "ptr" in main() is changed from "long *" to "short *", there will
be no warning (and no casts were used). There will be a bug lurking
however.
This bug is caused by a design flaw in fcn. Change the
prototype so that the call is fcn(ptr, sizeof *ptr, 10) and
the problem is gone. Be in the habit of casting malloc
and hand editing your entire code base whenever you
change a type, and you will probably not notice the
design flaw. Be in the habit of not casting malloc and
not editing your code base regularly, and the design
flaw will be obvious early.

--
Bill Pursell

Feb 9 '07 #107
Keith Thompson wrote:
Yevgen Muntyan <mu****************@tamu.eduwrites:
>Mark McIntyre wrote:
[...]
>>If you're compiling it with a C++ compiler, its C++ code. It may look
like C, it may also compile as C, but its C++, and probably badly
written C++ at that.
Okay, let's use this term: "C code which is intended to be compiled
both with C and C++ compilers". I mean "C code" by "C code", i.e.
the code which is C according to C standard and is compilable with
C compiler in conforming mode. Not sure it's strict enough, but hope
you get the idea (which you already got anyway, I believe).
And no, C code doesn't become C++ code because you feed it to g++, even
if C++ folks think it is :)

No, C code doesn't become C++ code because you feed it to g++. If g++
accepts it (assuming g++ to be a correctly working C++ compiler), then
it was *already* C++ code.

What you're talking about is code that is simultaneously C code and
C++ code.
Yes.
I don't want to get too deeply into this argument, but I will say
that, in my opinion, there is rarely a real need to write such code.
(I said "rarely", not "never".)
And this is the key point: "rarely" is not "never".
Though it's not really that rare, just look at /usr/include/*.h or
whatever_path\include\*.h. Lots of C code which is
intentionally made C++-compatible. Lately only die-hard
hate-c-plus-plus folks make public C headers not C++-compatible
if they want their libraries to be used. I indeed was
talking not about this (except the parts about headers
of course). I did talk about doing "g++ foo.c". Anyway,
nobody is really talking about technical stuff. Technical
stuff is used in this discussion to justify blind stupid
"Wrong period". Whatever.

Yevgen
Feb 9 '07 #108
CBFalconer wrote:
Richard Heathfield wrote:
>CBFalconer said:
>>Yevgen Muntyan wrote:

... snip ...

What promotes bad habits? Bad habits? Okay, let it be a bad habit
to cast return value of malloc (which I agree with if it's "always
cast"). Do you say that it's fine to claim that the cast in the
following code

#include <stdlib.h>
int main (void)
{
char *foo = (char*) malloc (18);
return 0;
}

*necessarily* and *always* leads to bad results for every single
person in every single situation? Please don't say about habits,
just say "yes" or "no" (and read the thread to see what I am
talking about if you're interested).

Always. He has typed at least eight unnecessary characters,
leading to broken fingernails, various muscular problems, not to
mention the extraneous discussion here and added probability of
spilling coffee (or other liquids) into the keyboard.

All most droll, Chuck, but...
>>The program
is also fatally flawed by failure to #include <stdlib.h>

...wrong...
>>, while the
inclusion of stdio.h is totally unnecessary (another 19 excess
chars typed).

...and wrong again.

Damn. I could have sworn I read stdio there. There goes my
perfect record. The nits are getting out of hand.
I have to revise that. Obviously I slipped into an alternate
universe, which explains the substitution of stdlib for stdio, and
preseves my impeccable record.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>

"A man who is right every time is not likely to do very much."
-- Francis Crick, co-discover of DNA
"There is nothing more amazing than stupidity in action."
-- Thomas Matthews
Feb 9 '07 #109
Yevgen Muntyan wrote:
>
.... snip ...
>
Oh yeah people in this thread did say that. That's what the
fuss is about.
High time to PLONK this useless thread.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>

"A man who is right every time is not likely to do very much."
-- Francis Crick, co-discover of DNA
"There is nothing more amazing than stupidity in action."
-- Thomas Matthews
Feb 9 '07 #110
Yevgen Muntyan said:
Richard Heathfield wrote:
<snip>
>>
I fail to see why:

p = ALLOC_A_THING(foo);

is more convenient than:

p = malloc(sizeof *p);

You fail to see, I don't. I like ALLOC_A_THING because
it describes the intent and hides the actual memory
allocation.
No, it doesn't, at least no more than malloc does. And even if it did,
which it doesn't, you still don't need the cast.
How
about custom_allocator_here() function?
Yeah, you wouldn't need a cast there either.

<snip>
>>Or

#define FOO_NEW() ((Foo*) malloc (sizeof (Foo))) // *must* cast here

Why? The cast doesn't do any good,

It saves your butt if you change type,
So let me get this straight - you're saying that if you're daft enough
to use the type in the sizeof, you have to write some otherwise
unnecessary code to give the compiler a fighting chance of warning you
about your daft decision, and only at the risk of suppressing another
warning about your daft decision? Yeah, that's true - constructing
daftness is not difficult in C, or in any language. So?

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Feb 9 '07 #111
Yevgen Muntyan said:

<snip>
It's easy to write lot of C code which is valid C++. You have to
apply casts to return value of malloc though.
It's *pointless* to write lots of C code which is valid C++. If you
can't take advantage of C++'s non-C features, why bother using it? And
if you can, then it's not compilable in C. And malloc makes for bad C++
programs, on the whole.
>>>2) C++ defines mechanisms to interface to C code that has been
compiled as C code.
>>And I am talking about compiling *C* code with *C++* compiler.

If you're compiling it with a C++ compiler, its C++ code. It may look
like C, it may also compile as C, but its C++, and probably badly
written C++ at that.

Okay, let's use this term: "C code which is intended to be compiled
both with C and C++ compilers".
Ah, you mean "bad code" (unless your name is P J Plauger, which it
isn't).
I mean "C code" by "C code", i.e.
the code which is C according to C standard and is compilable with
C compiler in conforming mode. Not sure it's strict enough, but hope
you get the idea (which you already got anyway, I believe).
And no, C code doesn't become C++ code because you feed it to g++,
even if C++ folks think it is :)
Right. Instead, if it's a *good* C program, it becomes a raw material
which the compiler uses to produce diagnostic messages. If it's a bad
or trivial C program, it might also be a valid C++ program. Such
multi-language programs are few and far between, but they do exist.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Feb 9 '07 #112
Yevgen Muntyan <mu****************@tamu.eduwrote:
Mark McIntyre wrote:
On Thu, 08 Feb 2007 13:14:44 -0600, in comp.lang.c , Yevgen Muntyan
<mu****************@tamu.eduwrote:

Flash wrote
>1) In C++ there are better methods than using malloc to get memory
You lose compatibility with C then ;)
Yes, people who think C and C++ are compatible often do seem to prefer
sloppy ill-defined compatibility over formal but slightly harder to
use compatibility. Smiley noted.

It's easy to write lot of C code which is valid C++. You have to
apply casts to return value of malloc though.
That's what Mark said: sloppy.

Richard
Feb 9 '07 #113
"matevzb" <ma*****@gmail.comwrote:
On Feb 8, 11:51 pm, CBFalconer <cbfalco...@yahoo.comwrote:
matevzb wrote:
I tend to disagree on this one. If you change the type of "ptr"
you *should* examine *all* the places where "ptr" was used anyhow
(not just the line with malloc). If you don't, that's promoting
bad habits and that may bite harder than the x*sizeof(<type>). I
personally always use the latter and have never had any trouble
with it.
Not necessary. If you have avoided unnecessary casts, the compiler
will point out any harmful type mismatches.
No, it won't in case of void *. A hypothetical case:
#include <stdlib.h>
#include <string.h>

typedef enum
{
SHORT = 0,
LONG = 1
} mytype;

int
fcn (void *array, mytype type, size_t size)
{
void *ptr;

switch (type)
{
case SHORT:
ptr = malloc (size * sizeof(short));
You didn't read the construct you're criticising, did you? You didn't
even read the reason why that construct is better, because here you're
demonstrating exactly why it is better than this code.

Again:

ptr=malloc(num * sizeof *ptr);

is always less likely to break than

ptr=malloc(num * sizeof(type));

If you choose to break that by using void * for everything and then
casting to random types, that's your problem, and it demonstrates
exactly nothing about the need to check anything in well-written C.

Richard
Feb 9 '07 #114
Richard Heathfield wrote:
Yevgen Muntyan said:

<snip>

>>It's easy to write lot of C code which is valid C++. You have to
apply casts to return value of malloc though.


It's *pointless* to write lots of C code which is valid C++. If you
can't take advantage of C++'s non-C features, why bother using it? And
if you can, then it's not compilable in C. And malloc makes for bad C++
programs, on the whole.
It's not pointless if you are using C++ for hardware simulations to test
your C drivers.

--
Ian Collins.
Feb 9 '07 #115
Ian Collins said:
Richard Heathfield wrote:
>Yevgen Muntyan said:

<snip>

>>>It's easy to write lot of C code which is valid C++. You have to
apply casts to return value of malloc though.


It's *pointless* to write lots of C code which is valid C++. If you
can't take advantage of C++'s non-C features, why bother using it?
And if you can, then it's not compilable in C. And malloc makes for
bad C++ programs, on the whole.
It's not pointless if you are using C++ for hardware simulations to
test your C drivers.
If you're using C++ for the hardware simulations, you're using C++, not
C.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Feb 9 '07 #116
Richard Heathfield wrote:
Ian Collins said:

>>Richard Heathfield wrote:
>>>Yevgen Muntyan said:

<snip>

It's easy to write lot of C code which is valid C++. You have to
apply casts to return value of malloc though.
It's *pointless* to write lots of C code which is valid C++. If you
can't take advantage of C++'s non-C features, why bother using it?
And if you can, then it's not compilable in C. And malloc makes for
bad C++ programs, on the whole.

It's not pointless if you are using C++ for hardware simulations to
test your C drivers.


If you're using C++ for the hardware simulations, you're using C++, not
C.
The driver code is C.

--
Ian Collins.
Feb 9 '07 #117
Ian Collins said:
Richard Heathfield wrote:
>Ian Collins said:
>>>Richard Heathfield wrote:
Yevgen Muntyan said:

>It's easy to write lot of C code which is valid C++. You have to
>apply casts to return value of malloc though.

It's *pointless* to write lots of C code which is valid C++. [...]

It's not pointless if you are using C++ for hardware simulations to
test your C drivers.

If you're using C++ for the hardware simulations, you're using C++,
not C.
The driver code is C.
Fine, in which case it isn't C++, so you don't need the cast on malloc.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Feb 9 '07 #118
On Feb 9, 5:39 am, "Bill Pursell" <bill.purs...@gmail.comwrote:
On Feb 9, 1:11 am, "matevzb" <mate...@gmail.comwrote:
On Feb 8, 11:51 pm, CBFalconer <cbfalco...@yahoo.comwrote:matevzb wrote:
I tend to disagree on this one. If you change the type of "ptr"
you *should* examine *all* the places where "ptr" was used anyhow
(not just the line with malloc). If you don't, that's promoting
bad habits and that may bite harder than the x*sizeof(<type>). I
personally always use the latter and have never had any trouble
with it.
Not necessary. If you have avoided unnecessary casts, the compiler
will point out any harmful type mismatches.
No, it won't in case of void *. A hypothetical case:
#include <stdlib.h>
#include <string.h>
typedef enum
{
SHORT = 0,
LONG = 1
} mytype;
int
fcn (void *array, mytype type, size_t size)
{
void *ptr;
switch (type)
{
case SHORT:
ptr = malloc (size * sizeof(short));
memcpy (ptr, array, size * sizeof(short));
break;
case LONG:
ptr = malloc (size * sizeof(long));
memcpy (ptr, array, size * sizeof(long));
break;
default:
return -1;
}
return 0;
}
int
main (void)
{
long *ptr = malloc (10 * sizeof *ptr);
memset (ptr, 1, 10 * sizeof *ptr);
fcn (ptr, LONG, 10);
return 0;
}
If "ptr" in main() is changed from "long *" to "short *", there will
be no warning (and no casts were used). There will be a bug lurking
however.

This bug is caused by a design flaw in fcn. Change the
prototype so that the call is fcn(ptr, sizeof *ptr, 10) and
the problem is gone. Be in the habit of casting malloc
and hand editing your entire code base whenever you
change a type, and you will probably not notice the
design flaw. Be in the habit of not casting malloc and
not editing your code base regularly, and the design
flaw will be obvious early.
You could put it that way. Unfortunately, I have to use a function
very similar to the abovementioned fcn() and it's part of an external
library on which I have no influence whatsoever (the function is used
for packing parameters for RPC calls). I don't use any unnecessary
casts, but using sizeof *ptr brings me no benefits. Perhaps it's a
design flaw, but I prefer to call it reality.
--
WYCIWYG - what you C is what you get

Feb 9 '07 #119
On Feb 9, 8:27 am, r...@hoekstra-uitgeverij.nl (Richard Bos) wrote:
"matevzb" <mate...@gmail.comwrote:
On Feb 8, 11:51 pm, CBFalconer <cbfalco...@yahoo.comwrote:
matevzb wrote:
I tend to disagree on this one. If you change the type of "ptr"
you *should* examine *all* the places where "ptr" was used anyhow
(not just the line with malloc). If you don't, that's promoting
bad habits and that may bite harder than the x*sizeof(<type>). I
personally always use the latter and have never had any trouble
with it.
Not necessary. If you have avoided unnecessary casts, the compiler
will point out any harmful type mismatches.
No, it won't in case of void *. A hypothetical case:
#include <stdlib.h>
#include <string.h>
typedef enum
{
SHORT = 0,
LONG = 1
} mytype;
int
fcn (void *array, mytype type, size_t size)
{
void *ptr;
switch (type)
{
case SHORT:
ptr = malloc (size * sizeof(short));

You didn't read the construct you're criticising, did you? You didn't
even read the reason why that construct is better, because here you're
demonstrating exactly why it is better than this code.

Again:

ptr=malloc(num * sizeof *ptr);

is always less likely to break than

ptr=malloc(num * sizeof(type));

If you choose to break that by using void * for everything and then
casting to random types, that's your problem, and it demonstrates
exactly nothing about the need to check anything in well-written C.
It's not my choice, see the reply to Bill Pursell. And of course it's
my problem, I have to use such code, be it well-written C or not.
--
WYCIWYG - what you C is what you get

Feb 9 '07 #120
"matevzb" <ma*****@gmail.comwrote:
On Feb 9, 8:27 am, r...@hoekstra-uitgeverij.nl (Richard Bos) wrote:
If you choose to break that by using void * for everything and then
casting to random types, that's your problem, and it demonstrates
exactly nothing about the need to check anything in well-written C.
It's not my choice, see the reply to Bill Pursell. And of course it's
my problem, I have to use such code, be it well-written C or not.
If it's foisted on you, it's not a very good example in a discussion
about what is and is not good design, though, is it?

I'm using

int WINAPI WinMain(HINSTANCE instance, HINSTANCE previnst__,
PSTR cmdline, int showmode)

because I have to. That doesn't mean I think it's good design to include
a function parameter you never use and haven't for years, or even that
the above is valid C.

Richard
Feb 9 '07 #121
Yevgen Muntyan wrote, On 09/02/07 00:34:
Flash Gordon wrote:
>Yevgen Muntyan wrote, On 08/02/07 19:14:
>>Flash Gordon wrote:
Yevgen Muntyan wrote, On 08/02/07 13:34:
Christopher Layne wrote:
>Yevgen Muntyan wrote:
<snip>
>>>However, the *habit* of casting is always a bad habit and the habit
of casting malloc is always a bad habit.

Yes, such a *habit* is bad. Did I tell it's not?

You seem to be saying there is nothing wrong with doing something even
though if it becomes a habit it is a bad habit. Habits are formed by
repeatedly doing things, so if you want to avoid having bad habits do
not engage in the practices which are bad habits.

I do not engage in those practices to my best knowledge. At least
not with casting return value of malloc. I don't cast it normally.
I do cast it when I need to (usually it's C++ or allocation
macros in headers). And I am not saying it's okay to cast stuff
here and there. I am saying that some folks in this newsgroup
must apply some consideration and thinking before spitting
stupid "Wrong."
You have yet to come up with a convincing reason for doing it, so there
is so far no convincing reason for people not to say it is the wrong
thing to do.
>>>I have seen exactly one person come up with a convincing reason why
he should cast the value returned by malloc in his specific
situation. That reason is at least in part due to commercial reality
rather than technical merit.

Note the compatibility with C++ is a bad reason because:
1) In C++ there are better methods than using malloc to get memory

You lose compatibility with C then ;)

Actually, than is not necessarily true. There are ways of creating
interfaces for C code to call C++ code.

Tenth time: *compiling* C code with C++ compiler. It is necessarily
true that C compiler won't accept "new Foo" (we don't talk crazy
"C/C++" compilers and funny macros, right?).
In that case, for the 11th time there is no reason to compile C code
with a C++ compiler. If you want to access C code from C++ then use the
methods defined in C++ otherwise don;t, but either way compile your C
code as C and your C++ code as C++.
>>>2) C++ defines mechanisms to interface to C code that has been
compiled as C code.

And I am talking about compiling *C* code with *C++* compiler.

Simple solution, don't do it. Apart from anything else there are
subtle differences between C and C++ such that a program can be valid
as both but behave differently.

And there is lot of C code which behaves in the same way. E.g.

foo.h:
---------------------------
#ifdef __cplusplus
extern "C" {
#endif

typedef struct Foo Foo;

void *alloc_some_mem (size_t n);

#define ALLOC_FOO() ((Foo*) alloc_some_mem (sizeof (Foo)))

#ifdef __cplusplus
}
#endif
---------------------------
Yes, it is the same. Whether presented to someone who know C or C++ they
will tell you it is the wrong thing to do. Given the above delete the
#define and just call alloc_some_mem when you want to use it, calling
from C code without the cast calling from C++ code with the cast
(although using it from C++ code would probably be a bad thing). So by
deleting one line the problem goes away.
I won't try to talk about other cases when one really wants to compile
his C code with C++ compiler, since there is an easy solution, "don't do
it". I really love these simple solutions: the problem is to do this
and this; the solution is not to do this and this and do that instead.
Works like a charm in an argument.
It is also the best solution. The languages *are* different. You don't
try to compile you C code with a Java compiler or run it in a Perl
interpreter, so why try to compile it with a C++ compiler?
--
Flash Gordon
Feb 9 '07 #122
Yevgen Muntyan wrote, On 09/02/07 04:47:
Keith Thompson wrote:
>Yevgen Muntyan <mu****************@tamu.eduwrites:
>>Mark McIntyre wrote:
[...]
>>>If you're compiling it with a C++ compiler, its C++ code. It may look
like C, it may also compile as C, but its C++, and probably badly
written C++ at that.
Okay, let's use this term: "C code which is intended to be compiled
both with C and C++ compilers". I mean "C code" by "C code", i.e.
the code which is C according to C standard and is compilable with
C compiler in conforming mode. Not sure it's strict enough, but hope
you get the idea (which you already got anyway, I believe).
And no, C code doesn't become C++ code because you feed it to g++, even
if C++ folks think it is :)

No, C code doesn't become C++ code because you feed it to g++. If g++
accepts it (assuming g++ to be a correctly working C++ compiler), then
it was *already* C++ code.

What you're talking about is code that is simultaneously C code and
C++ code.

Yes.
Now tell us why you want code that is both. A good technical reason not,
"well it means I can feed it to a C or a C++ compiler" since that is a
circular argument.
>I don't want to get too deeply into this argument, but I will say
that, in my opinion, there is rarely a real need to write such code.
(I said "rarely", not "never".)

And this is the key point: "rarely" is not "never".
Though it's not really that rare, just look at /usr/include/*.h or
whatever_path\include\*.h. Lots of C code which is
intentionally made C++-compatible. Lately only die-hard
hate-c-plus-plus folks make public C headers not C++-compatible
if they want their libraries to be used
How many times can you find casts of the return value of malloc in the
*headers*. Those headers are for defining interfaces and so should not
in general include code. After all, how would you use those libraries
from Ada, Fortran etc if it relies on code in C header files?
I indeed was
talking not about this (except the parts about headers
of course). I did talk about doing "g++ foo.c". Anyway,
nobody is really talking about technical stuff. Technical
stuff is used in this discussion to justify blind stupid
"Wrong period". Whatever.
You have yet to provide a good reason for feeding your C code to a C++
compiler so you have yet to back up your argument that it is not the
wrong thing to do.
--
Flash Gordon
Feb 9 '07 #123
On Feb 9, 10:36 am, r...@hoekstra-uitgeverij.nl (Richard Bos) wrote:
"matevzb" <mate...@gmail.comwrote:
On Feb 9, 8:27 am, r...@hoekstra-uitgeverij.nl (Richard Bos) wrote:
If you choose to break that by using void * for everything and then
casting to random types, that's your problem, and it demonstrates
exactly nothing about the need to check anything in well-written C.
It's not my choice, see the reply to Bill Pursell. And of course it's
my problem, I have to use such code, be it well-written C or not.

If it's foisted on you, it's not a very good example in a discussion
about what is and is not good design, though, is it?

I'm using

int WINAPI WinMain(HINSTANCE instance, HINSTANCE previnst__,
PSTR cmdline, int showmode)

because I have to. That doesn't mean I think it's good design to include
a function parameter you never use and haven't for years, or even that
the above is valid C.
Note that I didn't say that using sizeof *ptr is bad and that
sizeof(<type>) is good design. I was pointing out that in my opinion
sizeof(<type>) doesn't promote bad habits per se. To me, it's a
stylistic issue, and I haven't (yet) been convinced otherwise =) For
others of course, it may be more than that...
--
WYCIWYG - what you C is what you get

Feb 9 '07 #124
Yevgen Muntyan wrote:
Perhaps I should have said that I don't think casting return value of
malloc is a good idea? Instead of not-saying which gets interpreted
as saying-the-contrary.

Yevgen
Dude, cast malloc until the day you die then. Freedom for all malloc()
casters, la la la. It's not big enough to argue for a week, so I'm done with
this discussion.
Feb 9 '07 #125
Richard Bos wrote:
I'm using

int WINAPI WinMain(HINSTANCE instance, HINSTANCE previnst__,
PSTR cmdline, int showmode)

because I have to. That doesn't mean I think it's good design to include
a function parameter you never use and haven't for years, or even that
the above is valid C.

Richard
Ugh. Win32.

You've got to love API calls that take 13 parameters - 7 of which can randomly
be set to 0 or NULL (just decide at the flip of a coin) and no effect will be
noticed.
Feb 9 '07 #126
matevzb wrote:
Note that I didn't say that using sizeof *ptr is bad and that
sizeof(<type>) is good design. I was pointing out that in my opinion
sizeof(<type>) doesn't promote bad habits per se. To me, it's a
stylistic issue, and I haven't (yet) been convinced otherwise =) For
others of course, it may be more than that...
--
WYCIWYG - what you C is what you get
I guess you think it looks cleaner or more advanced or something of that
nature. When in the long run it's just more freakin' work with zero gain.
Feb 9 '07 #127
Yevgen Muntyan wrote:
You snipped the piece where I said when I need to. Sure, you
can say that I can just avoid using malloc and alike in headers.
The same "simple solution" as was offered elsewhere: avoid
situations where you need cast and you will not need cast.
But I still believe that

#define ALLOC_A_THING(Type) ((Type*) malloc (sizeof (Type)))

is not too bad.

Yevgen
I think you have a penchant for being needlessly contrary.
Feb 9 '07 #128
Yevgen Muntyan wrote:
Even with malloc this macro is more convenient than malloc(sizeof *foo)
or malloc(sizeof(Foo)) (given the name is better than
"custom_allocator_here"). Some people even believe it's safer than
raw malloc. Or

#define FOO_NEW() ((Foo*) malloc (sizeof (Foo))) // *must* cast here
No. It's not. It's not clear, it's obtuse and pointless monkeying that
*reduces* visible intent.
Feb 9 '07 #129
Richard Heathfield wrote:
Yevgen Muntyan said:
>Richard Heathfield wrote:
<snip>
>>I fail to see why:

p = ALLOC_A_THING(foo);

is more convenient than:

p = malloc(sizeof *p);
You fail to see, I don't. I like ALLOC_A_THING because
it describes the intent and hides the actual memory
allocation.

No, it doesn't, at least no more than malloc does. And even if it did,
which it doesn't, you still don't need the cast.
malloc(sizeof *ptr)

doesn't clearly state what it does. For you it does, you are used
to this construct and it's crystal clear to you. This is a style issue.
No less than

if (foo) {
do_something ();
}

vs

if (foo)
{
do_something ();
}
>
>How
about custom_allocator_here() function?

Yeah, you wouldn't need a cast there either.
Nah, tell how more convenient is

ptr = custom_allocator_with_some_options (sizeof *ptr, OPTIONS);

than

ptr = ALLOC_A_THING(Type);
<snip>
>>>Or

#define FOO_NEW() ((Foo*) malloc (sizeof (Foo))) // *must* cast here
Why? The cast doesn't do any good,
It saves your butt if you change type,

So let me get this straight - you're saying that if you're daft enough
to use the type in the sizeof, you have to write some otherwise
unnecessary code to give the compiler a fighting chance of warning you
about your daft decision, and only at the risk of suppressing another
warning about your daft decision?
Sorry, which one? Again casting from int to pointer? Oh yeah, compilers
are not obliged by holy standard to emit warnings about missing
prototypes, bummer.

You think that

ptr = malloc (sizeof *ptr)

is a nice workaround for typeless return value of malloc, I don't. I
think

((Type*) malloc (sizeof (Type)))

is better because it has a type. And, say, I like g_new(Foo, 1) better
because it says "allocate one Foo structure".
I can do

return g_new(Foo, 1);

or

Foo *ptr = g_new (Foo, 1);

Anyway, here's another real piece of code:

http://svn.gnome.org/viewcvs/glib/tr....h?view=markup

You can claim how much you want that I am stupid, authors
of that code are stupid, that it's nice to use void* when you
allocate memory, but not everyone agrees with that. Now you can
repeat the killer argument about Elvis to complete proof
of you being right.

Yevgen
Feb 9 '07 #130
Christopher Layne wrote:
Yevgen Muntyan wrote:
>Even with malloc this macro is more convenient than malloc(sizeof *foo)
or malloc(sizeof(Foo)) (given the name is better than
"custom_allocator_here"). Some people even believe it's safer than
raw malloc. Or

#define FOO_NEW() ((Foo*) malloc (sizeof (Foo))) // *must* cast here

No. It's not. It's not clear, it's obtuse and pointless monkeying that
*reduces* visible intent.
What do you do if you need to replace malloc() with another allocator?
Grep? While this macro is indeed stupid, it was an example of where
cast is needed.
*If* you write a macro which allocates a Foo structure (this macro can
do arbitrary nice or complex things, and there *are* macros like that
in real code) you better make it of type Foo*.

Yevgen
Feb 9 '07 #131
Yevgen Muntyan wrote:

malloc(sizeof *ptr)

doesn't clearly state what it does. For you it does, you are used
to this construct and it's crystal clear to you. This is a style issue.
No less than
Yes it does clearly state it. Go read up on the C language.
Nah, tell how more convenient is

ptr = custom_allocator_with_some_options (sizeof *ptr, OPTIONS);

than

ptr = ALLOC_A_THING(Type);
ALLOC_A_THING() does not take options. They aren't even the same. You're
arguing specific purpose vs generic purpose. Go back and try again.
You think that

ptr = malloc (sizeof *ptr)

is a nice workaround for typeless return value of malloc, I don't. I
think
This is NOT a workaround. It has NOTHING to do with types. It has everything
to do with tying the size to the identifier itself and indirectly that size
being a *resultant value base on the identifier* which means you change
things in *one* place, not *two*.
((Type*) malloc (sizeof (Type)))

is better because it has a type. And, say, I like g_new(Foo, 1) better
because it says "allocate one Foo structure".
I can do
Please go read up on C again or something along those lines. You don't NEED to
cast the value returned. It does not do anything for the type, and providing
an actual type to sizeof does not influence malloc() in any way. malloc()
does not care about types! It allocates dynamic memory, that's it.

It seems at this point your insistance on the applicability of casting is
borne out of a refusal to perceive things in a different way than you have
trained yourself to do.
Feb 9 '07 #132
Richard Heathfield wrote:
Yevgen Muntyan said:
>Richard Heathfield wrote:
<snip>
>>I fail to see why:

p = ALLOC_A_THING(foo);

is more convenient than:

p = malloc(sizeof *p);
You fail to see, I don't. I like ALLOC_A_THING because
it describes the intent and hides the actual memory
allocation.

No, it doesn't, at least no more than malloc does. And even if it did,
which it doesn't, you still don't need the cast.
>How
about custom_allocator_here() function?

Yeah, you wouldn't need a cast there either.
It seems I forgot that you're talking here about strictly conforming
code here. Indeed, if you have a strictly conforming program then
you're limited to bunch of C files without any non-standard headers,
and any custom allocator business or libraries or anything like that
is out question. A header like

foo.h:

#define FOO_NEW() ...

simply can't be in a strictly conforming program and you use
only malloc(whatever) (or calloc, etc.) in your code. Yes, using only
standard features promotes use of raw malloc, and yes, casting
raw malloc in regular code like

int func (..)
{
...
ptr = malloc (anything);
...
}

is not good.

Yevgen
Feb 9 '07 #133
Christopher Layne wrote:
Yevgen Muntyan wrote:

>malloc(sizeof *ptr)

doesn't clearly state what it does. For you it does, you are used
to this construct and it's crystal clear to you. This is a style issue.
No less than

Yes it does clearly state it. Go read up on the C language.
>Nah, tell how more convenient is

ptr = custom_allocator_with_some_options (sizeof *ptr, OPTIONS);

than

ptr = ALLOC_A_THING(Type);

ALLOC_A_THING() does not take options. They aren't even the same. You're
arguing specific purpose vs generic purpose. Go back and try again.
>You think that

ptr = malloc (sizeof *ptr)

is a nice workaround for typeless return value of malloc, I don't. I
think

This is NOT a workaround. It has NOTHING to do with types. It has everything
to do with tying the size to the identifier itself and indirectly that size
being a *resultant value base on the identifier* which means you change
things in *one* place, not *two*.
>((Type*) malloc (sizeof (Type)))

is better because it has a type. And, say, I like g_new(Foo, 1) better
because it says "allocate one Foo structure".
I can do

Please go read up on C again or something along those lines. You don't NEED to
cast the value returned. It does not do anything for the type, and providing
an actual type to sizeof does not influence malloc() in any way. malloc()
does not care about types! It allocates dynamic memory, that's it.
Exactly, malloc is typeless. And it's good to wrap blind typeless malloc
into a macro which gets an expression which does have type. I NEED to
cast return value to get an expression with type, because I want that
expression to have type. I NEED an expression which reads "allocate one
Foo structure". I don't like an expression which reads "allocate
sizeof(the-type-of-this-pointer-dereferenced) bytes". I want compiler
to warn me if I assign that Foo* to a variable of wrong type or
return it from a function with different return type, or feed it to
a function with different type of argument.
It seems at this point your insistance on the applicability of casting is
borne out of a refusal to perceive things in a different way than you have
trained yourself to do.
I guess you're right here to some extent. Or maybe I refuse to do things
in a worse way than I do them now?

Yevgen
Feb 9 '07 #134
Richard Bos wrote:
"matevzb" <ma*****@gmail.comwrote:
>On Feb 8, 11:51 pm, CBFalconer <cbfalco...@yahoo.comwrote:
>>matevzb wrote:
I tend to disagree on this one. If you change the type of "ptr"
you *should* examine *all* the places where "ptr" was used anyhow
(not just the line with malloc). If you don't, that's promoting
bad habits and that may bite harder than the x*sizeof(<type>). I
personally always use the latter and have never had any trouble
with it.
Not necessary. If you have avoided unnecessary casts, the compiler
will point out any harmful type mismatches.
No, it won't in case of void *. A hypothetical case:
#include <stdlib.h>
#include <string.h>

typedef enum
{
SHORT = 0,
LONG = 1
} mytype;

int
fcn (void *array, mytype type, size_t size)
{
void *ptr;

switch (type)
{
case SHORT:
ptr = malloc (size * sizeof(short));

You didn't read the construct you're criticising, did you? You didn't
even read the reason why that construct is better, because here you're
demonstrating exactly why it is better than this code.

Again:

ptr=malloc(num * sizeof *ptr);

is always less likely to break than

ptr=malloc(num * sizeof(type));
It's likely to break hard when ptr has different type from what
really needs to be allocated. And that happens (and you said "always").
If you choose to break that by using void * for everything and then
casting to random types, that's your problem,
No, it's your problem that you apply this kind of arguments like
"casting to random types", so that the guy you are replying to
sounds like an idiot which really casts stuff to random types.

Yevgen
Feb 9 '07 #135
Yevgen Muntyan wrote:
> ptr=malloc(num * sizeof *ptr);

is always less likely to break than

ptr=malloc(num * sizeof(type));

It's likely to break hard when ptr has different type from what
really needs to be allocated. And that happens (and you said "always").
Which is more likely to happen with the second case. You're flip flopping
around here.
>If you choose to break that by using void * for everything and then
casting to random types, that's your problem,

No, it's your problem that you apply this kind of arguments like
"casting to random types", so that the guy you are replying to
sounds like an idiot which really casts stuff to random types.
Okay programmer insecurity counseling time.
Feb 9 '07 #136
Yevgen Muntyan wrote:
>>#define FOO_NEW() ((Foo*) malloc (sizeof (Foo))) // *must* cast here

No. It's not. It's not clear, it's obtuse and pointless monkeying that
*reduces* visible intent.

What do you do if you need to replace malloc() with another allocator?
Grep? While this macro is indeed stupid, it was an example of where
cast is needed.
*If* you write a macro which allocates a Foo structure (this macro can
do arbitrary nice or complex things, and there *are* macros like that
in real code) you better make it of type Foo*.

Yevgen
What are you NOT getting about the fact that the cast is not needed in ISO C?
Do you know the purpose and characteristics of void pointers?

malloc() takes a size_t, that is IT. It does not talk to, worth with, or have
beers with sizeof to figure out what the type is.
Feb 9 '07 #137
Yevgen Muntyan wrote:
It seems I forgot that you're talking here about strictly conforming
code here. Indeed, if you have a strictly conforming program then
[...]
foo.h:

#define FOO_NEW() ...

simply can't be in a strictly conforming program and you use
only malloc(whatever) (or calloc, etc.) in your code. Yes, using only
standard features promotes use of raw malloc, and yes, casting
raw malloc in regular code like
At this point I can't tell if you're trolling or just don't know what you're
talking about Yevgen.

Feb 9 '07 #138
Richard Bos wrote:
Ryan Ply <th******@earthling.netwrote:
>rl*@hoekstra-uitgeverij.nl (Richard Bos) writes:
>>I don't use Emac-OS, and even if I did, abrv. mode would not solve the
more important problem of making the malloc()-caster less attentive. As
for "solving" the warnings, that's like "solving" a stinging pain in
your right side by taking morphine. Yes, it _does_ get rid of the pain,
but you'll still die of a burst appendix sooner or later. It's better
get rid of the cause of the pain (read: warning messages) than to ignore
it.
People just like reading whatever they want instead of whats on the
screen in front of them. Someone said that by casting it would hide or
mask the compilers warnings to me. I put extra flags in so that these
warnings return as if nothing happened. Thus "solved".

Wrong.
> I program for real targets, not would be possible maybe in some day
embedded targets 20 years form now possibly.

The meaning of that sentence is as muddled as its grammar.
>That is how specific compiler options are safe to use for me.

Wrong.
> When I get a project with a vague target then
things will be different, but that hasn't happened to date.

But don't mind me; just don't come whining when your habit of ignoring
valid warnings comes back to bite you in the arse.
Since the discussing went too far from here, let me repeat the MAIN
point. I was replying to this thing, that Richard Bos said Ryan Ply
ignored valid warnings while Ryan Ply actually made his compiler
to warn about real problem. The real (potential) problem is missing
header which leads to UB, not converting int to pointer which is a bogus
side effect.

And what I am saying is: you got to read very very carefully
what you are replying to if you are going to use these stupid
"Wrong period Don't come whining when...".

Yevgen
Feb 9 '07 #139
Christopher Layne wrote:
Yevgen Muntyan wrote:
>It seems I forgot that you're talking here about strictly conforming
code here. Indeed, if you have a strictly conforming program then
[...]
foo.h:

#define FOO_NEW() ...

simply can't be in a strictly conforming program and you use
only malloc(whatever) (or calloc, etc.) in your code. Yes, using only
standard features promotes use of raw malloc, and yes, casting
raw malloc in regular code like

At this point I can't tell if you're trolling or just don't know what you're
talking about Yevgen.
Give me a program which has #include "foo.h" and I'll provide
you with a conforming implementation (made of gcc and python)
which will refuse to compile it. And I am serious. It was
quite a discovery for me when I read the standard about the
#include directive.
Moreover, you may say that it will be a perverse implementation,
whatever, but you try to create a folder with includes named
"bits" or "linux" and your project, and then tell whose fault
it doesn't compile on linux, your or it's perverse linux implementation?

As to what I said about Richard Heathfield, that's another thing.
He really ignores any issues in code which is off-topic in this
newsgroup. If you do "foo = something_not_standard()", he will
say it's off-topic, and you can't prove anything about how and
where to use something_not_standard() since it doesn't exist.

If I argue about this casting thing, I can only provide an example
with malloc, but I won't make macros like that with malloc! I would
make them with something_very_non_standard_but_with_same_properti es,
but I can't use it here since it's off-topic. Or Richard won't
even consider those or treat them as they are the *same* as malloc.
Etc.

Yevgen
Feb 9 '07 #140
Christopher Layne wrote:
Yevgen Muntyan wrote:
>>>#define FOO_NEW() ((Foo*) malloc (sizeof (Foo))) // *must* cast here
No. It's not. It's not clear, it's obtuse and pointless monkeying that
*reduces* visible intent.
What do you do if you need to replace malloc() with another allocator?
Grep? While this macro is indeed stupid, it was an example of where
cast is needed.
*If* you write a macro which allocates a Foo structure (this macro can
do arbitrary nice or complex things, and there *are* macros like that
in real code) you better make it of type Foo*.

Yevgen

What are you NOT getting about the fact that the cast is not needed in ISO C?
Do you know the purpose and characteristics of void pointers?
You're not kidding, are you? I said *I need* cast because I want a safer
expression. If I apply cast, the expression acquires a type.

((Type*) malloc (sizeof (Type)))

is a standalone expression of type Type* (and it's an allocated chunk
of memory). Of course I can avoid cast here, but I believe void* is
worse than Type* when I need Type*.

I do get the fact that cast is not needed in ISO C.
malloc() takes a size_t, that is IT. It does not talk to, worth with, or have
beers with sizeof to figure out what the type is.
Yep, and this is why I apply cast to make an expression which has beer
with its argument every Friday.

Yevgen
Feb 9 '07 #141
Christopher Layne wrote:
Yevgen Muntyan wrote:
>> ptr=malloc(num * sizeof *ptr);

is always less likely to break than

ptr=malloc(num * sizeof(type));
It's likely to break hard when ptr has different type from what
really needs to be allocated. And that happens (and you said "always").

Which is more likely to happen with the second case. You're flip flopping
around here.
Nope. It is not "more likely to happen" if you use real correct type
you need. If you do

struct Child {
Parent p;
...
};

Parent *ptr = malloc (sizeof (Child))

or similarly

Parent *ptr = some_func (sizeof (Child));

where some_func does some job inside, you're fine; but

Parent *ptr = malloc (sizeof *ptr);

is broken. And things like this happen.

You don't feel it's really a style issue, do you.

Yevgen
Feb 9 '07 #142
Yevgen Muntyan wrote:
You're not kidding, are you? I said *I need* cast because I want a safer
expression. If I apply cast, the expression acquires a type.

((Type*) malloc (sizeof (Type)))
Here's a grand concept:

1. Don't use sizeof(Type) to malloc().
2. Don't use the wrong allocation functions within the functional context you
desire.
3. If you need to allocate memory for an aggregate type such as a structure,
do indeed do what you're referring to, and wrap that up in it's own
blah_new() function. However, you still wouldn't cast malloc within that
function either.
4. If you do need a custom allocator, which refers back to 3 above, you won't
be returning the value of ((Type *)malloc(sizeof (Type)) because you actually
have to do something *custom* to the new object in the first place.
5. If you cannot prevent yourself from writing code like the following:

char *q;
q = malloc(sizeof(struct i_want_c_plus_plus));

Then what do you expect?
It's the entire reason we're advocating not writing sizeof (type) in there in
the first place. Now, I know you're going to go back to "custom allocator",
well...

*This* is an example of a real world "custom allocator":

thing *thing_new(void)
{
thing *t;

t = malloc(sizeof *t); /* no sizeof (thing) and no cast */
if (t == NULL) problem();
t->flags = THING_FLAGS_DEFAULT;
t->queue = thing_queue_new();
t->mutex = malloc(sizeof *t->mutex);
mutex_init(t->mutex, NULL);
t->newsreader = 0;
t->stop_posting = 1;

return t;
}

That's actually doing something like initializing lower level entities the
caller doesn't need to know about and encapsulating common tasks to one area.

This, on the other hand...

thing *thing_new(void)
{
return malloc(sizeof (thing)); /* no cast */
}

Is not a custom allocator. If anything it's just a waste of space. But notice
I didn't cast malloc() there either?

Feb 9 '07 #143
Yevgen Muntyan wrote:
Nope. It is not "more likely to happen" if you use real correct type
you need. If you do

struct Child {
Parent p;
...
};

Parent *ptr = malloc (sizeof (Child))
Which of course would actually be wrong based on your example.
or similarly

Parent *ptr = some_func (sizeof (Child));

where some_func does some job inside, you're fine; but

Parent *ptr = malloc (sizeof *ptr);

is broken. And things like this happen.
It's completely not broken.
You don't feel it's really a style issue, do you.

Yevgen
What exactly is your issue? Get your types right in the first place and you
won't have to use a bunch of goofy language tricks to catch straight up bad
programming.

You want C to be C++. Not gonna happen.
Feb 9 '07 #144
Christopher Layne wrote:
Yevgen Muntyan wrote:
>You're not kidding, are you? I said *I need* cast because I want a safer
expression. If I apply cast, the expression acquires a type.

((Type*) malloc (sizeof (Type)))

Here's a grand concept:

1. Don't use sizeof(Type) to malloc().
Because it's wrong, huh?
2. Don't use the wrong allocation functions within the functional context you
desire.
3. If you need to allocate memory for an aggregate type such as a structure,
do indeed do what you're referring to, and wrap that up in it's own
blah_new() function. However, you still wouldn't cast malloc within that
function either.
If I call malloc in code, i.e. if I write in a function body

.... malloc (...);

then I won't cast it. Who said I do?
4. If you do need a custom allocator, which refers back to 3 above, you won't
be returning the value of ((Type *)malloc(sizeof (Type)) because you actually
have to do something *custom* to the new object in the first place.
5. If you cannot prevent yourself from writing code like the following:

char *q;
q = malloc(sizeof(struct i_want_c_plus_plus));
Sorry, I do not write code like that. And if I use nicish macro
with a cast, I can't write such code again because compiler will
tell I am converting wrong stuff to wrong stuff.
Then what do you expect?
It's the entire reason we're advocating not writing sizeof (type) in there in
the first place. Now, I know you're going to go back to "custom allocator",
well...
Nah, custom allocator meant replacement for malloc(), not foo_new()
which does more than allocating memory. Anyway, here you go:

http://svn.gnome.org/viewcvs/glib/tr....h?view=markup

Nobody is putting

"(Type*) malloc (sizeof (Type))"

literally in code. But "g_new(Type, 1)" is a nicer expression saying
"allocate one Type structure". Now you may not think it's nicer, but
I do think it is. And I think it's a style issue. You like void*,
I don't. And I am not the person trying to convince the other to do
what he does here. I'm fine with others doing malloc(sizeof *ptr).
I am not fine with others telling me to do that and trying to prove
that that form is better while it's not.
Feb 9 '07 #145
Yevgen Muntyan wrote, On 09/02/07 12:47:
Christopher Layne wrote:
>Yevgen Muntyan wrote:

>>malloc(sizeof *ptr)

doesn't clearly state what it does. For you it does, you are used
to this construct and it's crystal clear to you. This is a style issue.
No less than

Yes it does clearly state it. Go read up on the C language.
>>Nah, tell how more convenient is

ptr = custom_allocator_with_some_options (sizeof *ptr, OPTIONS);

than

ptr = ALLOC_A_THING(Type);

ALLOC_A_THING() does not take options. They aren't even the same. You're
arguing specific purpose vs generic purpose. Go back and try again.
I note you failed to address the point about your example not being
applicable.
>>You think that

ptr = malloc (sizeof *ptr)

is a nice workaround for typeless return value of malloc, I don't. I
think

This is NOT a workaround. It has NOTHING to do with types. It has
everything
to do with tying the size to the identifier itself and indirectly that
size
being a *resultant value base on the identifier* which means you change
things in *one* place, not *two*.
You also fail to address this point.
>>((Type*) malloc (sizeof (Type)))

is better because it has a type. And, say, I like g_new(Foo, 1) better
because it says "allocate one Foo structure".
I can do

Please go read up on C again or something along those lines. You don't
NEED to
cast the value returned. It does not do anything for the type, and
providing
an actual type to sizeof does not influence malloc() in any way. malloc()
does not care about types! It allocates dynamic memory, that's it.

Exactly, malloc is typeless. And it's good to wrap blind typeless malloc
into a macro which gets an expression which does have type. I NEED to
cast return value to get an expression with type, because I want that
expression to have type. I NEED an expression which reads "allocate one
Foo structure". I don't like an expression which reads "allocate
sizeof(the-type-of-this-pointer-dereferenced) bytes".
Then write a fooalocator function that returns a pointer to a properly
initialised foo. It *still* does not need a cast.
I want compiler
to warn me if I assign that Foo* to a variable of wrong type or
return it from a function with different return type, or feed it to
a function with different type of argument.
If the function takes bar* and you pass it a foo* then the compiler
*will* warn you, this has nothing to do with casting the value returned
by malloc. The same for return values.
>It seems at this point your insistance on the applicability of casting is
borne out of a refusal to perceive things in a different way than you
have
trained yourself to do.

I guess you're right here to some extent. Or maybe I refuse to do things
in a worse way than I do them now?
No, you refuse to admit to the possibility that what has been suggested
might be better. You seem to ignore at least half the counter points to
your argument. Arguing with someone who does not address the counters to
the points he raises is pointless, so bye.
--
Flash Gordon
Feb 9 '07 #146
Flash Gordon wrote:
Yevgen Muntyan wrote, On 09/02/07 12:47:
>Christopher Layne wrote:
>>Yevgen Muntyan wrote:
malloc(sizeof *ptr)

doesn't clearly state what it does. For you it does, you are used
to this construct and it's crystal clear to you. This is a style issue.
No less than

Yes it does clearly state it. Go read up on the C language.

Nah, tell how more convenient is

ptr = custom_allocator_with_some_options (sizeof *ptr, OPTIONS);

than

ptr = ALLOC_A_THING(Type);

ALLOC_A_THING() does not take options. They aren't even the same. You're
arguing specific purpose vs generic purpose. Go back and try again.

I note you failed to address the point about your example not being
applicable.
ALLOC_A_THING passes default options to
custom_allocator_with_some_options. And yes, I am talking about specific
cases of course. It's said here "ALLOC_A_THING" is never
needed/good/better. I am saying that

ALLOC_A_THING()

may be much better than

alloc_something (sizeof (ThatType), FOO_BAR | FOO_BAZ);
>>>You think that

ptr = malloc (sizeof *ptr)

is a nice workaround for typeless return value of malloc, I don't. I
think

This is NOT a workaround. It has NOTHING to do with types. It has
everything
to do with tying the size to the identifier itself and indirectly
that size
being a *resultant value base on the identifier* which means you change
things in *one* place, not *two*.

You also fail to address this point.
I didn't want just to say that yes that IS a workaround. You have
to use nasty sizeof *ptr to make sure size if correct there. I believe
another workaround is better: provide correct type and make the result
have that type instead of void*. And "better" here means "nicer for me,
and no worse in any technical aspect".
>>>((Type*) malloc (sizeof (Type)))

is better because it has a type. And, say, I like g_new(Foo, 1) better
because it says "allocate one Foo structure".
I can do

Please go read up on C again or something along those lines. You
don't NEED to
cast the value returned. It does not do anything for the type, and
providing
an actual type to sizeof does not influence malloc() in any way.
malloc()
does not care about types! It allocates dynamic memory, that's it.

Exactly, malloc is typeless. And it's good to wrap blind typeless malloc
into a macro which gets an expression which does have type. I NEED to
cast return value to get an expression with type, because I want that
expression to have type. I NEED an expression which reads "allocate one
Foo structure". I don't like an expression which reads "allocate
sizeof(the-type-of-this-pointer-dereferenced) bytes".

Then write a fooalocator function that returns a pointer to a properly
initialised foo. It *still* does not need a cast.
Now your argument is "don't do this and do that instead". You may think
it's good to write thousand

AnyStruct *
any_struct_new (void)
{
return malloc (sizeof (AnyStruct));
}

functions, duplicate them in all source files since they must be static
(or make sure their names don't clash with anything else, and then
make sure the symbols are not exported from the lib), I don't think so.
Now, if there is no allocate_foo(), then if I need raw chunk of memory
for struct Foo, I prefer an expression of type Foo* to an expression
of type void*.
I want compiler
to warn me if I assign that Foo* to a variable of wrong type or
return it from a function with different return type, or feed it to
a function with different type of argument.

If the function takes bar* and you pass it a foo* then the compiler
*will* warn you, this has nothing to do with casting the value returned
by malloc. The same for return values.
How about assignment? Your workaround is to use "sizeof *ptr" thing,
mine is to use an expression of correct type. As to arguments and
return values I was thinking rather of

Something *func (void)
{
return malloc (sizeof (Something));
}

(the fooallocator function). This is a bit silly example of course,
but though it's already better than invocation of malloc right in code;
and I sometimes have such functions to make them do more later.
Yeah yeah, I *must* make it

Something *func (void)
{
Something *s;
s = malloc (sizeof (Something));
return s;
}

to avoid being beaten by typeless malloc.
>>It seems at this point your insistance on the applicability of
casting is
borne out of a refusal to perceive things in a different way than you
have
trained yourself to do.

I guess you're right here to some extent. Or maybe I refuse to do things
in a worse way than I do them now?

No, you refuse to admit to the possibility that what has been suggested
might be better. You seem to ignore at least half the counter points to
your argument. Arguing with someone who does not address the counters to
the points he raises is pointless, so bye.
It's hard to argue here and address same points again and again,
and it's hard to express what I think in English, and it's hard
to filter valid questions out of "wrong." junk. See, you are asking
technical questions, and then you make a conclusion about insistance,
refusal, and other words I hardly understand. And then you're saying
I must answer your questions or otherwise it's pointless to talk
to me, but I am stubborn as a donkey in any case, right from start.

Bye.
Feb 9 '07 #147
Yevgen Muntyan wrote:
functions, duplicate them in all source files since they must be static
(or make sure their names don't clash with anything else, and then
make sure the symbols are not exported from the lib), I don't think so.
Now, if there is no allocate_foo(), then if I need raw chunk of memory
for struct Foo, I prefer an expression of type Foo* to an expression
of type void*.
You want C++.
How about assignment? Your workaround is to use "sizeof *ptr" thing,
mine is to use an expression of correct type. As to arguments and
return values I was thinking rather of

Something *func (void)
{
return malloc (sizeof (Something));
}
You want C++.
(the fooallocator function). This is a bit silly example of course,
but though it's already better than invocation of malloc right in code;
and I sometimes have such functions to make them do more later.
Yeah yeah, I *must* make it

Something *func (void)
{
Something *s;
s = malloc (sizeof (Something));
return s;
}

to avoid being beaten by typeless malloc.
So you think the previous function is going to somehow magically return void *
to it's callers? They're both going to return pointer to Something.

You want C++.
It's hard to argue here and address same points again and again,
and it's hard to express what I think in English, and it's hard
to filter valid questions out of "wrong." junk. See, you are asking
technical questions, and then you make a conclusion about insistance,
refusal, and other words I hardly understand. And then you're saying
I must answer your questions or otherwise it's pointless to talk
to me, but I am stubborn as a donkey in any case, right from start.
You're scared of malloc() (which to a *C* programmer is like a hammer to a
carpenter).

You want C++.

Feb 9 '07 #148
[Others here have responded eloquently to Mr Muntyan's reply to my reply
somewhat upthread, so I'll let that go, and focus on where we've got
to.]

Yevgen Muntyan said:
Flash Gordon wrote:
>Yevgen Muntyan wrote, On 09/02/07 12:47:
<snip>
>>I don't like an expression which reads
"allocate sizeof(the-type-of-this-pointer-dereferenced) bytes".

Then write a fooalocator function that returns a pointer to a
properly initialised foo. It *still* does not need a cast.

Now your argument is "don't do this and do that instead". You may
think it's good to write thousand

AnyStruct *
any_struct_new (void)
{
return malloc (sizeof (AnyStruct));
}

functions,
No, that would be daft, because you're not adding any value over malloc
itself, so you might as well just do:

AnyStruct *p = malloc(sizeof *p);

Where the thousand functions score is in initialising objects properly.
For example:

AnyStruct *any_struct_new(int x, int y, double z)
{
AnyStruct blank = {0};
AnyStruct *new = malloc(sizeof *new);
if(new != NULL)
{
*new = blank; /* make all values determinate
(if considered desirable) */
new->x = x;
new->y = y;
new->z = z;
}
return new;
}
duplicate them in all source files since they must be
static (or make sure their names don't clash with anything else, and
then make sure the symbols are not exported from the lib),
<shrugI don't see this as a big deal. Naming conventions can handle
it.
I don't think so.
I do.
Now, if there is no allocate_foo(), then if I need raw chunk
of memory for struct Foo, I prefer an expression of type Foo* to an
expression of type void*.
That's your choice, but it doesn't actually buy you any type safety.

<snip>

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Feb 9 '07 #149
Christopher Layne wrote:
Yevgen Muntyan wrote:
>functions, duplicate them in all source files since they must be static
(or make sure their names don't clash with anything else, and then
make sure the symbols are not exported from the lib), I don't think so.
Now, if there is no allocate_foo(), then if I need raw chunk of memory
for struct Foo, I prefer an expression of type Foo* to an expression
of type void*.

You want C++.
Nope.
>How about assignment? Your workaround is to use "sizeof *ptr" thing,
mine is to use an expression of correct type. As to arguments and
return values I was thinking rather of

Something *func (void)
{
return malloc (sizeof (Something));
}

You want C++.
Sure you know better.
>(the fooallocator function). This is a bit silly example of course,
but though it's already better than invocation of malloc right in code;
and I sometimes have such functions to make them do more later.
Yeah yeah, I *must* make it

Something *func (void)
{
Something *s;
s = malloc (sizeof (Something));
return s;
}

to avoid being beaten by typeless malloc.

So you think the previous function is going to somehow magically return void *
to it's callers? They're both going to return pointer to Something.
Yes. And

Something *func (void)
{
return malloc (sizeof (OopsWrongType));
}

is going to return pointer to Something too.
You want C++.
Sure.
>It's hard to argue here and address same points again and again,
and it's hard to express what I think in English, and it's hard
to filter valid questions out of "wrong." junk. See, you are asking
technical questions, and then you make a conclusion about insistance,
refusal, and other words I hardly understand. And then you're saying
I must answer your questions or otherwise it's pointless to talk
to me, but I am stubborn as a donkey in any case, right from start.

You're scared of malloc() (which to a *C* programmer is like a hammer to a
carpenter).
I am scared of void*. Was beaten by this beast not once.
You want C++.
Absolutely. Doing C++ since now on, right away.

Yevgen
Feb 9 '07 #150

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

Similar topics

5
by: disco | last post by:
I am working on this example from a book "C Primer Plus" by Prata 4th edition - p. 672. There is no erata on this problem at the publisher's website. 1) Is it a violation of copyright laws to...
12
by: f.oppedisano | last post by:
Hi, i would like to allocate two structures making only one malloc call. So i do prt=malloc(sizeof(struct1)+sizeof(struct2)); After this operation i make two pointers one to the first struct...
11
by: Rodrigo Dominguez | last post by:
there are sometimes that I use third party libraries, I use some functions that returns char * or structs, etc. sometimes the memory that is returned by those libraries, when I try to free this...
6
by: Fernando Cacciola | last post by:
Help me out here please: While watching Brad Abraham's MSDN TV talk about the Dispose pattern, refering to: public virtual void Dispose ( bool disposing ) { if ( disposing ) { <-- WHAT...
4
by: Atul Sureka | last post by:
Hi, I want to free the object memory in C# - like we do using 'delete' keyword in C++. Lets say I have an object of some class and I want to explicitly free the memory. C# do not have any free...
66
by: karthikbalaguru | last post by:
Hi, Will 'free' return the memory Immediately to the OS ? Thx in advans, Karthik Balaguru
9
by: david | last post by:
I will past only two segments from the code it should be enough to see what I did wrong, I think I know there I made a mistake, but how to fix it I can not tell. This why I need help from you all....
11
by: vivek | last post by:
Hello, I have a pointer to a main structure which again consists of structures, enums, char, int, float and again complex structures. When i free all the contents of the main structure, it...
25
by: Andreas Eibach | last post by:
Hi again, one of the other big woes I'm having... typedef struct perBlockStru /* (structure) Long words per block */ { unsigned long *lword; } lwperBlockStru_t;
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
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...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
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...

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.