Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > malloc(0)

Reply
Thread Tools

malloc(0)

 
 
Jack Klein
Guest
Posts: n/a
 
      09-06-2004
On Sun, 05 Sep 2004 02:27:08 -0400, Kai-Uwe Bux <(E-Mail Removed)>
wrote in comp.lang.c++:

> E. Robert Tisdale wrote:
> > You should always free storage that you allocate:

> ^^^^^^
>
> Why?
>
> In the case under discussion, the operating system will reclaim all
> allocated memory since the program is about to die anyway. I do see no
> point in freeing the memory myself.


Much as I dislike agreeing with the troll Tisdale, he is perfectly
correct here.

Exactly where in the C++ standard does it state that allocated memory
not released by a program will be reclaimed by the operating system?
Where is the guarantee that this works on all implementations and all
platforms?

And of course what happens when someone tries to reuse the code inside
a larger program by renaming main()?

Sloppy programming habits should never be encouraged. Or even
tolerated.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
 
Reply With Quote
 
 
 
 
Jack Klein
Guest
Posts: n/a
 
      09-06-2004
On Sat, 04 Sep 2004 22:50:25 -0400, Kai-Uwe Bux <(E-Mail Removed)>
wrote in comp.lang.c++:

> john smith wrote:
>
> > Can someone please explain to me what is happening when I do a malloc(0).
> >
> > This is what I did.
> >
> > int* p = (int*)malloc(0);
> >
> > Then I printed the value of p and of course it was non-null.
> >
> > But has it allocated memory or what?
> >

>
> Sure, it has allocated a block of length 0. I have no idea what you want to
> do with a block that small, but I am sure that malloc has just allocated a
> block of that size, after all that is what malloc is supposed to do
> according to its man page.


That is one of the two defined actions that malloc() may take. The
other is to return a null pointer.

> > I would think that it would return a null.

>
> Why? It returns the location in memory where the allocated block starts.
> That this block has *length* 0 does not imply that it should start at the
> *location* 0.


What do you think that a null pointer has to do with location 0? A
null pointer does not point to location 0. It does not even have an
all-bits zero representation on all platforms.

If there is a location 0 on a platform and it is valid for a C (or
C++) object to reside there, then a pointer to such an object would be
a pointer to location 0 and it would most specifically not be a null
pointer.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
 
Reply With Quote
 
 
 
 
David Hilsee
Guest
Posts: n/a
 
      09-06-2004
"E. Robert Tisdale" <(E-Mail Removed)> wrote in message
news:che7lm$iji$(E-Mail Removed)...
> Kai-Uwe Bux wrote:
>
> > I guess, you wrote a program whose behavior is undefined;
> > and you happend to get away with it this time
> > for a particular implementation.
> >
> > #include <cstdlib>
> > #include <iostream>
> >
> > struct xxx {
> > char banner [26];
> > };
> >
> > int main( void ) {
> > xxx* p = (xxx*)malloc(0*sizeof(xxx));
> > xxx* q = (xxx*)malloc(0*sizeof(xxx));
> >
> > std::strcpy( p->banner, "Hello folks, how are you?" );
> > std::strcpy( q->banner, "Hello folks, how are you?" );
> >
> > std::cout << "p->banner: " << p->banner << "\n";
> > std::cout << "q->banner: " << q->banner << "\n";
> >
> > return 0;
> > }
> >
> >>g++ scratch.cc
> >>a.out

> >
> > p->banner: Hello folks, howHello folks, how are you?
> > q->banner: Hello folks, how are you?

>
> You should always free storage that you allocate:

<snip>

You didn't free the storage in your original example, either. What happens
when you "correct" it?

--
David Hilsee


 
Reply With Quote
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      09-06-2004
Jack Klein wrote:

> On Sat, 04 Sep 2004 22:50:25 -0400, Kai-Uwe Bux <(E-Mail Removed)>
> wrote in comp.lang.c++:
>
>> john smith wrote:
>>
>> > Can someone please explain to me what is happening when I do a
>> > malloc(0).
>> >
>> > This is what I did.
>> >
>> > int* p = (int*)malloc(0);
>> >
>> > Then I printed the value of p and of course it was non-null.
>> >
>> > But has it allocated memory or what?
>> >

>>
>> Sure, it has allocated a block of length 0. I have no idea what you want
>> to do with a block that small, but I am sure that malloc has just
>> allocated a block of that size, after all that is what malloc is supposed
>> to do according to its man page.

>
> That is one of the two defined actions that malloc() may take. The
> other is to return a null pointer.


Actually, I was completely wrong, but maybe notin the way you may have had
in mind primarily.

As far as I can tell from the standard, which I have read now, every call
to malloc, regardless of the argument, may return a null pointer any time.
As far as I can see, the standard makes no guarantees that calls to malloc
"succeed". So there is no difference between malloc(0) and malloc(n). The
standard just allows explicitly that every call malloc(0) may fail,
however, I cannot see that it does not allow that for other values too. In
fact, I do not see any language in the standard that would rule out the
following most useless implementation:

void* malloc( size_t size ) {
return( NULL );
}


Besides, the OP explictly mentioned that malloc(0) did not return 0 and
asked what was going on. So, I was describing what happens for a succesful
call to malloc(0), and I was mistaken on a subtle point. I thought,
incorrectly, that malloc(0) had allocated a chunk of size 0. In particular,
I thought that subsequent calls to malloc(0) may return the same pointer.
That, however, may not be allowed:

If the size of the space requested is zero, the behavior is
implementation-defined: either a null-pointer is returned, or
the behavior is *as if the size were some nonzero value*, except
that the returned pointer shall not be used to access an object.

Thus, if malloc(0) does not return 0, it shall behave as though it was
called with a non-zero argument. I read this to imply that two successive
calls to malloc(0), neither of which returns 0, must return different
values. This is an extra requirement that would not otherwise follow from
the usual requirement that allocated blocks are to be disjoint.


>> > I would think that it would return a null.

>>
>> Why? It returns the location in memory where the allocated block starts.
>> That this block has *length* 0 does not imply that it should start at the
>> *location* 0.

>
> What do you think that a null pointer has to do with location 0? A
> null pointer does not point to location 0. It does not even have an
> all-bits zero representation on all platforms.
>
> If there is a location 0 on a platform and it is valid for a C (or
> C++) object to reside there, then a pointer to such an object would be
> a pointer to location 0 and it would most specifically not be a null
> pointer.
>


You are right, I was sloppy.

Just an asside triggered by your remark: is the numerical constant 0 (say
as an int or unsigned int) required to have an all-bits zeror
epresentation?


Best

Kai-Uwe Bux
 
Reply With Quote
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      09-06-2004
Jack Klein wrote:

> On Sun, 05 Sep 2004 02:27:08 -0400, Kai-Uwe Bux <(E-Mail Removed)>
> wrote in comp.lang.c++:
>
>> E. Robert Tisdale wrote:
>> > You should always free storage that you allocate:

>> ^^^^^^
>>
>> Why?
>>
>> In the case under discussion, the operating system will reclaim all
>> allocated memory since the program is about to die anyway. I do see no
>> point in freeing the memory myself.

>
> Much as I dislike agreeing with the troll Tisdale, he is perfectly
> correct here.
>
> Exactly where in the C++ standard does it state that allocated memory
> not released by a program will be reclaimed by the operating system?
> Where is the guarantee that this works on all implementations and all
> platforms?
>


Interesting question, however, your concern will not be cured by the call
to free() that was proposed. From the C standard:

The free function causes the space pointed to by ptr to be deallocated,
that is, made available for further allocation. ...

Since this part is inherited by C++, and since C++ does only specify the
observable behavior of a single instruction sequence, the phrase "available
for further allocation" just refers to the very C++ programm that is
calling free(), i.e, subsequence calls to malloc() or new() may now return
this memory. There is, as far as I can see, no gurantee whatsoever in the C
or C++ standard that space deallocated by free() or delete() is returned to
the operating system (thereby becomming available to *other programs*)?

Where do you get your guarantee that freeing memory works as you seem to
expect?


> And of course what happens when someone tries to reuse the code inside
> a larger program by renaming main()?
>
> Sloppy programming habits should never be encouraged. Or even tolerated.


My understanding of sloppyness is something along the lines of "not
thinking about what I code". I question rules that contain the word
"always" or "never" because, more often than not, they encourage sloppyness
in this sense. For example, reusing main() by renaming without reading it
would be sloppy.

Besides, the example was meant to illustrate a point under discussion and
not teach how to programm -- it exhibits undefined behavior anyway.


Best

Kai-Uwe Bux
 
Reply With Quote
 
Ioannis Vranos
Guest
Posts: n/a
 
      09-06-2004
Kai-Uwe Bux wrote:

> Thus, if malloc(0) does not return 0, it shall behave as though it was
> called with a non-zero argument. I read this to imply that two successive
> calls to malloc(0), neither of which returns 0, must return different
> values.



Now we got in this really useless stuff, but the standard does not
require pointers on different objects to have different values.

Pointer comparison may happen only for the same object or sequence of
objects.






Regards,

Ioannis Vranos

http://www23.brinkster.com/noicys
 
Reply With Quote
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      09-06-2004
Ioannis Vranos wrote:

> Kai-Uwe Bux wrote:
>
>> Thus, if malloc(0) does not return 0, it shall behave as though it was
>> called with a non-zero argument. I read this to imply that two successive
>> calls to malloc(0), neither of which returns 0, must return different
>> values.

>
>
> Now we got in this really useless stuff, but the standard does not
> require pointers on different objects to have different values.
>
> Pointer comparison may happen only for the same object or sequence of
> objects.
>


For comparisions of pointers to objects not in the same sequence, I think
the standard allows the use of std::less< PointerType > and its relatives.
By 20.3.3/8 this is supposed to yield a total order.

Nonetheless, I am confused. I was thinking that malloc(n) is inherited from
C and governed by the language of the C standard with some modifications
from 20.4.6. Thus, malloc() returns void* (whatever that is) and not a
pointer to some object. The requirement is just that it is alligned
suitably so that it can be assigned to any pointer variable.

Moreover, malloc(n) shall, if called successfully, return the lowest byte
of some chunk of size at least n. Now, how am I to interpret the rule that
subsequent calls to malloc shall return pointers to disjoint chunks? Do you
claim that it was permissible for the returned values of type void* to
agree, yet they would somehow manage to refer to the lowest bytes of
disjoint chunks of memory?

I guess, what I claim is that

#include <iostream>
#include <functional>

int main ( void ) {
void* p = malloc(0);
void* q = malloc(0);
if ( ( p != 0 ) && ( q != 0 ) ){
if ( std::equal_to< void* >()( p, q ) ) {
std::cout << "unexpected result.\n";
}
}
}

is not supposed to print something.


Best

Kai-Uwe Bux

 
Reply With Quote
 
Old Wolf
Guest
Posts: n/a
 
      09-06-2004
Kai-Uwe Bux <(E-Mail Removed)> wrote:
> Ioannis Vranos wrote:
>
> > Kai-Uwe Bux wrote:
> >
> >> Thus, if malloc(0) does not return 0, it shall behave as though it was
> >> called with a non-zero argument. I read this to imply that two successive
> >> calls to malloc(0), neither of which returns 0, must return different
> >> values.

> >
> > Now we got in this really useless stuff, but the standard does not
> > require pointers on different objects to have different values.


It does for objects of the same type. I wonder what 'different values'
means for objects of incompatible types. For example:
union { int a; float b; } u;
can you say that &u.a and &u.b are the same value? Is it well-defined
to compare &u.a to &u.b (even after casting to void *) ? Of course,
casting to void* means the value may change.

> > Pointer comparison may happen only for the same object or sequence of
> > objects.


Pointers to different objects of compatible types can be checked
with ==.

> For comparisions of pointers to objects not in the same sequence, I think
> the standard allows the use of std::less< PointerType > and its relatives.
> By 20.3.3/8 this is supposed to yield a total order.


Useful.

> Moreover, malloc(n) shall, if called successfully, return the lowest byte
> of some chunk of size at least n. Now, how am I to interpret the rule that
> subsequent calls to malloc shall return pointers to disjoint chunks? Do you
> claim that it was permissible for the returned values of type void* to
> agree, yet they would somehow manage to refer to the lowest bytes of
> disjoint chunks of memory?


No, the values returned by malloc must all be different, ie.
void *p = malloc(0);
void *q = malloc(0);
assert( !p || !q || p != q );
 
Reply With Quote
 
Gianni Mariani
Guest
Posts: n/a
 
      09-07-2004
Old Wolf wrote:
.... really major nit pick ... excuse me.
>
> No, the values returned by malloc must all be different, ie.
> void *p = malloc(0);
> void *q = malloc(0);
> assert( !p || !q || p != q );


assert( !p || p != q );

I can move on now that I have removed that thorn


 
Reply With Quote
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      09-07-2004
Old Wolf wrote:

> Kai-Uwe Bux <(E-Mail Removed)> wrote:
>> Ioannis Vranos wrote:
>>
>> > Kai-Uwe Bux wrote:
>> >
>> >> Thus, if malloc(0) does not return 0, it shall behave as though it was
>> >> called with a non-zero argument. I read this to imply that two
>> >> successive calls to malloc(0), neither of which returns 0, must return
>> >> different values.
>> >
>> > Now we got in this really useless stuff, but the standard does not
>> > require pointers on different objects to have different values.

>
> It does for objects of the same type. I wonder what 'different values'
> means for objects of incompatible types. For example:
> union { int a; float b; } u;
> can you say that &u.a and &u.b are the same value? Is it well-defined
> to compare &u.a to &u.b (even after casting to void *) ? Of course,
> casting to void* means the value may change.
>


You can say that &u.a and &u.b have the same value when converted to void*.
From the standard [5.9]:

If two pointers point to data members of the same union object, they
compare equal (after conversion to void*, if necessary).


>> > Pointer comparison may happen only for the same object or sequence of
>> > objects.

>
> Pointers to different objects of compatible types can be checked
> with ==.
>
>> For comparisions of pointers to objects not in the same sequence, I think
>> the standard allows the use of std::less< PointerType > and its
>> relatives. By 20.3.3/8 this is supposed to yield a total order.

>
> Useful.
>


Essential: you need to have this for containers like std::set<T*>. By 5.9,
the built in operator< is undefined for T* if the pointers do not happen to
point to members of the same object or array.


>> Moreover, malloc(n) shall, if called successfully, return the lowest byte
>> of some chunk of size at least n. Now, how am I to interpret the rule
>> that subsequent calls to malloc shall return pointers to disjoint chunks?
>> Do you claim that it was permissible for the returned values of type
>> void* to agree, yet they would somehow manage to refer to the lowest
>> bytes of disjoint chunks of memory?

>
> No, the values returned by malloc must all be different, ie.
> void *p = malloc(0);
> void *q = malloc(0);
> assert( !p || !q || p != q );


That is how I understand the language of the standard, too.


Best

Kai-Uwe Bux
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off




Advertisments