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

F

Flash Gordon

Yevgen Muntyan wrote, On 09/02/07 00:34:
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.
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++.
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?
 
R

Richard Bos

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
 
F

Flash Gordon

Yevgen Muntyan wrote, On 09/02/07 04:47:
Keith said:
Yevgen Muntyan said:
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.
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.
 
M

matevzb

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...
 
C

Christopher Layne

Yevgen said:
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.
 
C

Christopher Layne

Richard said:
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.
 
C

Christopher Layne

matevzb said:
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...

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.
 
C

Christopher Layne

Yevgen said:
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.
 
C

Christopher Layne

Yevgen said:
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.
 
Y

Yevgen Muntyan

Richard said:
Yevgen Muntyan said:


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 ();
}
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);
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/trunk/glib/gmem.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
 
Y

Yevgen Muntyan

Christopher said:
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
 
C

Christopher Layne

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.
 
Y

Yevgen Muntyan

Richard said:
Yevgen Muntyan said:


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.


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
 
Y

Yevgen Muntyan

Christopher said:
Yevgen Muntyan wrote:



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


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.


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*.


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
 
Y

Yevgen Muntyan

Richard said:
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
 
C

Christopher Layne

Yevgen said:
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.
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.
 
C

Christopher Layne

Yevgen said:
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.
 
C

Christopher Layne

Yevgen said:
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.
 
Y

Yevgen Muntyan

Richard said:
The meaning of that sentence is as muddled as its grammar.


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
 
Y

Yevgen Muntyan

Christopher said:
Yevgen said:
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_properties,
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
 

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,262
Messages
2,571,058
Members
48,769
Latest member
Clifft

Latest Threads

Top