2000-11-07 03:59:31

by RAJESH BALAN

[permalink] [raw]
Subject: malloc(1/0) ??

hi,
why does this program works. when executed, it doesnt
give a segmentation fault. when the program requests
memory, is a standard chunk is allocated irrespective
of the what the user specifies. please explain.

main()
{
char *s;
s = (char*)malloc(0);
strcpy(s,"fffff");
printf("%s\n",s);
}

NOTE:
i know its a 'C' problem. but i wanted to know how
this works


__________________________________________________
Do You Yahoo!?
Thousands of Stores. Millions of Products. All in one Place.
http://shopping.yahoo.com/


2000-11-07 06:40:06

by Dan Kegel

[permalink] [raw]
Subject: Re: malloc(1/0) ??

[email protected] asked:
> [Why does this program not crash?]
>
> main()
> {
> char *s;
> s = (char*)malloc(0);
> strcpy(s,"fffff");
> printf("%s\n",s);
> }

It doesn't crash because the standard malloc is
optimized for speed, not for finding bugs.

Try linking it with a debugging malloc, e.g.
cc bug.c -lefence
and watch it dump core.

- Dan

2000-11-07 07:16:30

by jdow

[permalink] [raw]
Subject: Re: malloc(1/0) ??

From: "Dan Kegel" <[email protected]>
> [email protected] asked:
> > [Why does this program not crash?]
> >
> > main()
> > {
> > char *s;
> > s = (char*)malloc(0);
> > strcpy(s,"fffff");
> > printf("%s\n",s);
> > }
>
> It doesn't crash because the standard malloc is
> optimized for speed, not for finding bugs.
>
> Try linking it with a debugging malloc, e.g.
> cc bug.c -lefence
> and watch it dump core.

I'm not sure that is fully responsive, Dan. Why doesn't the
strcpy throw a hissyfit and coredump?

{^_^}

2000-11-07 07:52:49

by David Schwartz

[permalink] [raw]
Subject: RE: malloc(1/0) ??

> From: "Dan Kegel" <[email protected]>
> > [email protected] asked:
> > > [Why does this program not crash?]
> > >
> > > main()
> > > {
> > > char *s;
> > > s = (char*)malloc(0);
> > > strcpy(s,"fffff");
> > > printf("%s\n",s);
> > > }
> >
> > It doesn't crash because the standard malloc is
> > optimized for speed, not for finding bugs.
> >
> > Try linking it with a debugging malloc, e.g.
> > cc bug.c -lefence
> > and watch it dump core.
>
> I'm not sure that is fully responsive, Dan. Why doesn't the
> strcpy throw a hissyfit and coredump?

Why should it? Do you think that when you allocate memory, the chunk of
mappable memory you got always ends on the exact byte you asked it to? When
you invoke undefined behavior, anything can happen.

DS

2000-11-07 07:54:29

by David Schwartz

[permalink] [raw]
Subject: RE: malloc(1/0) ??

> hi,
> why does this program works. when executed, it doesnt
> give a segmentation fault. when the program requests
> memory, is a standard chunk is allocated irrespective
> of the what the user specifies. please explain.
>
> main()
> {
> char *s;
> s = (char*)malloc(0);
> strcpy(s,"fffff");
> printf("%s\n",s);
> }
>
> NOTE:
> i know its a 'C' problem. but i wanted to know how
> this works

The program does not work. A program works if it does what it's supposed to
do. If you want to argue that this program is supposed to print "ffffff"
then explain to me why the 'malloc' contains a zero in parenthesis.

The program can't possibly work because it invokes undefined behavior. It
is impossible to determine what a program that invokes undefined behavior is
'supposed to do'.

DS

2000-11-07 08:09:50

by Lyle Coder

[permalink] [raw]
Subject: Re: malloc(1/0) ??

When a program does a malloc... the glibc gets atleast on page (brk)
[actually, glibs determins of it needs to brk more memory from the kernel...
because it maintains it;s own pool].. so if you malloc 4 byts, you can copy
to that pointer more than 4 bytes (upto a page size, ex 4K)... hope that
answers one of your questions... as far as why malloc(0) works... I dunno

Best Wishes,
Lyle
----- Original Message -----
From: "David Schwartz" <[email protected]>
To: "RAJESH BALAN" <[email protected]>; <[email protected]>
Sent: Monday, November 06, 2000 11:54 PM
Subject: RE: malloc(1/0) ??


> > hi,
> > why does this program works. when executed, it doesnt
> > give a segmentation fault. when the program requests
> > memory, is a standard chunk is allocated irrespective
> > of the what the user specifies. please explain.
> >
> > main()
> > {
> > char *s;
> > s = (char*)malloc(0);
> > strcpy(s,"fffff");
> > printf("%s\n",s);
> > }
> >
> > NOTE:
> > i know its a 'C' problem. but i wanted to know how
> > this works
>
> The program does not work. A program works if it does what it's supposed
to
> do. If you want to argue that this program is supposed to print "ffffff"
> then explain to me why the 'malloc' contains a zero in parenthesis.
>
> The program can't possibly work because it invokes undefined behavior. It
> is impossible to determine what a program that invokes undefined behavior
is
> 'supposed to do'.
>
> DS
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> Please read the FAQ at http://www.tux.org/lkml/
>

2000-11-07 08:36:13

by Andrej Hosna

[permalink] [raw]
Subject: RE: malloc(1/0) ??

Hello ,
> > why does this program works. when executed, it doesnt
> > give a segmentation fault. when the program requests
> > memory, is a standard chunk is allocated irrespective
> > of the what the user specifies. please explain.
> >
> > main()
> > {
> > char *s;
> > s = (char*)malloc(0);
> > strcpy(s,"fffff");
> > printf("%s\n",s);
> > }
> >
> > NOTE:
> > i know its a 'C' problem. but i wanted to know how
> > this works

C problem? You would better say , library problem(but it's not a problem at
all).

> The program does not work. A program works if it does what it's supposed to
> do. If you want to argue that this program is supposed to print "ffffff"
> then explain to me why the 'malloc' contains a zero in parenthesis.
>
> The program can't possibly work because it invokes undefined behavior. It
> is impossible to determine what a program that invokes undefined behavior is
> 'supposed to do'.

I dont think it's undefined behaviour ...

Text from malloc.c <glibc2.something>
<------snip-------->
Malloc Algorithm:

The requested size is first converted into a usable form, `nb'.
This currently means to add 4 bytes overhead plus possibly more to
obtain 8-byte alignment and/or to obtain a size of at least
MINSIZE (currently 16, 24, or 32 bytes), the smallest allocatable
size. (All fits are considered `exact' if they are within MINSIZE
bytes.)
<----- snip --------->
So some area of MINSIZE is alloced , and you can write there...
Problems will arrive with writing over this area, and overwriting next memory
chunk header. Write is not a problem ... in your code you have 4KB to spare,
but when you try to free() you'd probably get SIGSEG.

Hope that you have idea how it works now. If not, read the malloc.c comments to
find about about how malloc realy works.

Adino
--
/* Andrej Hosna - http://people.ibl.sk/adino - +421 903 852 696 */
/* IBL Software Engineering - http://www.ibl.sk - +421 7 43427214 */

2000-11-07 08:46:55

by Matti Aarnio

[permalink] [raw]
Subject: Re: malloc(1/0) ??

On Tue, Nov 07, 2000 at 12:09:09AM -0800, Lyle Coder wrote:
> When a program does a malloc... the glibc gets atleast on page (brk)
> [actually, glibs determins of it needs to brk more memory from the kernel...
> because it maintains it;s own pool].. so if you malloc 4 byts, you can copy
> to that pointer more than 4 bytes (upto a page size, ex 4K)... hope that
> answers one of your questions... as far as why malloc(0) works... I dunno

Maybe following extract from glibc's malloc/malloc.c beginning
comments can help you there:


Minimum overhead per allocated chunk: 4 or 8 bytes
Each malloced chunk has a hidden overhead of 4 bytes holding size
and status information.

Minimum allocated size: 4-byte ptrs: 16 bytes (including 4 overhead)
8-byte ptrs: 24/32 bytes (including, 4/8 overhead)

When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte
ptrs but 4 byte size) or 24 (for 8/8) additional bytes are
needed; 4 (8) for a trailing size field
and 8 (16) bytes for free list pointers. Thus, the minimum
allocatable size is 16/24/32 bytes.

Even a request for zero bytes (i.e., malloc(0)) returns a
pointer to something of the minimum allocatable size.

Maximum allocated size: 4-byte size_t: 2^31 - 8 bytes
8-byte size_t: 2^63 - 16 bytes



Other systems (malloc libraries) may have different strategies on this
allocation management issue, thus allocating anything smaller than the
needed size is bound to get user burned. malloc(0) is insane thing
(IMO), but at least glibc supports it for some reason. Likely just due
to padding and minimum size issues.

> Best Wishes,
> Lyle

2000-11-07 08:50:46

by David Schwartz

[permalink] [raw]
Subject: RE: malloc(1/0) ??


> > The program can't possibly work because it invokes undefined
> behavior. It
> > is impossible to determine what a program that invokes
> undefined behavior is
> > 'supposed to do'.
>
> I dont think it's undefined behaviour ...

You are correct. This is bahavior that is undefined by the C language, but
defined by the implementation. So determining what the program was supposed
to do requires determining whether the person who wrote it was familiar with
the implementation on which it is being used. Amusingly, this means the
program is supposed to do different things depending upon what
implementation of malloc you have.

IIRC, malloc(0) is defined to return a unique block of memory that it is
valid to pass to free. However, doing anything with this memory (read/write)
is undefined by the C standard.

DS

2000-11-07 16:12:41

by Jesse Pollard

[permalink] [raw]
Subject: RE: malloc(1/0) ??


>
> > hi,
> > why does this program works. when executed, it doesnt
> > give a segmentation fault. when the program requests
> > memory, is a standard chunk is allocated irrespective
> > of the what the user specifies. please explain.
> >
> > main()
> > {
> > char *s;
> > s = (char*)malloc(0);
> > strcpy(s,"fffff");
> > printf("%s\n",s);
> > }
> >
> > NOTE:
> > i know its a 'C' problem. but i wanted to know how
> > this works
>
> The program does not work. A program works if it does what it's supposed to
> do. If you want to argue that this program is supposed to print "ffffff"
> then explain to me why the 'malloc' contains a zero in parenthesis.
>
> The program can't possibly work because it invokes undefined behavior. It
> is impossible to determine what a program that invokes undefined behavior is
> 'supposed to do'.

All true, but the reason it "works" is that malloc WILL allocate some memory,
even if it's only a few bytes of header.:

| | (other memory block controled by malloc/free...)
|-------|
| header|
| | - address returned to program
| next |
| header| (next memory block...)

Now the strcpy may have copied the string "fffff" over the next header.
The copy worked, the printf worked (its buffers were already allocated...)
BUT... If you allocate more memory via malloc, you will get an error
(eventually). I believe malloc(0) allocates 4 bytes as a minimum, though
this particular call IS undefined. You also did not check to see if
malloc did return something (It did, or you would have gotten a segmentation
fault from writing to location 0 with strcpy).

-------------------------------------------------------------------------
Jesse I Pollard, II
Email: [email protected]

Any opinions expressed are solely my own.

2000-11-07 16:39:47

by lost

[permalink] [raw]
Subject: RE: malloc(1/0) ??

> > > main()
> > > {
> > > char *s;
> > > s = (char*)malloc(0);
> > > strcpy(s,"fffff");
> > > printf("%s\n",s);
> > > }

I rather suspect that the strcpy() scribbled over malloc()s record keeping
data. However, that memory was in the processes allowed address space so
it didn't SIGSEGV. Now, when you call printf(), there is a very good
chance that printf() tried to allocate some sort of buffer space since it
is the first call to printf() in the program. Now, since malloc()s heap is
messed up from the strcpy(), it crashes. (Probably because
malloc() followed a pointer off into never-never land.) Hence, the crash
appears in printf() instead of strcpy() or malloc(). I won't repeat the
discussion about why malloc(0) succeeded.

William Astle
finger [email protected] for further information

-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GCS/M/S d- s+:+ !a C++ UL++++$ P++ L+++ !E W++ !N w--- !O !M PS PE V-- Y+
PGP t+@ 5++ X !R tv+@ b+++@ !DI D? G e++ h+ y?
------END GEEK CODE BLOCK------

2000-11-07 23:34:12

by Igmar Palsenberg

[permalink] [raw]
Subject: Re: malloc(1/0) ??

On Mon, 6 Nov 2000, RAJESH BALAN wrote:

> hi,
> why does this program works. when executed, it doesnt
> give a segmentation fault. when the program requests
> memory, is a standard chunk is allocated irrespective
> of the what the user specifies. please explain.
>
> main()
> {
> char *s;
> s = (char*)malloc(0);

malloc(0) is bogus in this case. malloc(0) == free();

> strcpy(s,"fffff");
> printf("%s\n",s);
> }
>
> NOTE:
> i know its a 'C' problem. but i wanted to know how
> this works

The most plausible reason is you're not crossing a page boundary, and you
don't get a access violation.



Igmar

2000-11-07 23:41:56

by Igmar Palsenberg

[permalink] [raw]
Subject: Re: malloc(1/0) ??


> I'm not sure that is fully responsive, Dan. Why doesn't the
> strcpy throw a hissyfit and coredump?

Because he's a lucky guy and doesn't cross a page boundary. If the
"ffff" thing is the entire Wind95 source code it will dump :-)

> {^_^}


Igmar

2000-11-07 23:44:59

by Igmar Palsenberg

[permalink] [raw]
Subject: RE: malloc(1/0) ??


> The program does not work. A program works if it does what it's supposed to
> do. If you want to argue that this program is supposed to print "ffffff"
> then explain to me why the 'malloc' contains a zero in parenthesis.
>
> The program can't possibly work because it invokes undefined behavior. It
> is impossible to determine what a program that invokes undefined behavior is
> 'supposed to do'.

May I remind you guys that a malloc(0) is equal to a free(). There is no
way that any mem get's malloced.

You only get a coredump if the program accesses a page it shouln't, and
since whe're talking 5 bytes here or so, you have a change that you don't
cross a boundary.

> DS


Igmar

2000-11-07 23:47:22

by Igmar Palsenberg

[permalink] [raw]
Subject: Re: malloc(1/0) ??

On Tue, 7 Nov 2000, Lyle Coder wrote:

> When a program does a malloc... the glibc gets atleast on page (brk)
> [actually, glibs determins of it needs to brk more memory from the kernel...
> because it maintains it;s own pool].. so if you malloc 4 byts, you can copy
> to that pointer more than 4 bytes (upto a page size, ex 4K)... hope that
> answers one of your questions... as far as why malloc(0) works... I dunno

Hmm.. Don't read a manpage in the middle of the night.. the issue is only
with realloc(0) that is equal to free().

Maybe one of the glibc guys can tell what the behaviour is with malloc(0).

> Best Wishes,
> Lyle


Igmar

2000-11-08 00:29:59

by Rogier Wolff

[permalink] [raw]
Subject: Re: malloc(1/0) ??

Matti Aarnio wrote:
> needed size is bound to get user burned. malloc(0) is insane thing
> (IMO), but at least glibc supports it for some reason. Likely just due
> to padding and minimum size issues.

Part of the desing of the C language and the library is intended to
make boundary conditions go well automatically.

So, a program that does:

fscanf (file, "%d", &numsquares);
squares = malloc (sizeof (struct square) * numsquares);
for (i=0;i<numsquares; i++)
read_square_from_file (file, &squares[i]);

fscanf (file, "%d", &numtriangles);
triangles = malloc (sizeof (struct triangle) * numtriangles);
for (i=0;i<numtriangles; i++)
read_triangle_from_file (file, &triangles[i]);


[use the stuff....]

free (triangles);
free (squares);

should work. See, the "for" loop nicely executes 0 times when
numtriangles is zero. Similarly, malloc/free don't have any
"exception" case for the "numtriangles is zero" case.

Now, at first you might say that "malloc" could return NULL, as long
as "free" accepts it. However, that's not true: The result of the
malloc call can and acutally should be checked for "NULL", and the
program might abort.

A valid implementation MAY:


#define NIL ((void *) 1)

void * malloc (int size)
{
if (size == 0) NIL;
[....]
}

void free (void *ptr)
{
if (ptr == NIL) return;
[...]
}

This way all should work. However someone mentioned that the returns
from "malloc" should be unique. Why would that be? That would prohibit
my "1" trick. The statement implies you want to go about checking
pointers for equality. If for example you have a memcmp (a, b) that
has "if (a == b) return 0;" at the beginning. That would be allowed
for the NIL pointers. (all malloc-0 results SHOULD compare equal
anyway: there are 0 differences....)

Roger.

--
** [email protected] ** http://www.BitWizard.nl/ ** +31-15-2137555 **
*-- BitWizard writes Linux device drivers for any device you may have! --*
* Common sense is the collection of *
****** prejudices acquired by age eighteen. -- Albert Einstein ********

2000-11-08 00:36:41

by David Schwartz

[permalink] [raw]
Subject: RE: malloc(1/0) ??


> This way all should work. However someone mentioned that the returns
> from "malloc" should be unique. Why would that be? That would prohibit
> my "1" trick. The statement implies you want to go about checking
> pointers for equality. If for example you have a memcmp (a, b) that
> has "if (a == b) return 0;" at the beginning. That would be allowed
> for the NIL pointers. (all malloc-0 results SHOULD compare equal
> anyway: there are 0 differences....)

It's a SuSv2 thing:

"Upon successful completion with size not equal to 0, malloc() returns a
pointer to the allocated space. If size is 0, either a null pointer or a
unique pointer that can be successfully passed to free() will be returned.
Otherwise, it returns a null pointer and sets errno to indicate the error."

DS

2000-11-08 01:29:53

by Tim Waugh

[permalink] [raw]
Subject: Re: malloc(1/0) ??

On Wed, Nov 08, 2000 at 01:41:40AM +0100, Igmar Palsenberg wrote:

> malloc(0) is bogus in this case. malloc(0) == free();

No, you're thinking of realloc.

Tim.
*/


Attachments:
(No filename) (165.00 B)
(No filename) (232.00 B)
Download all attachments

2000-11-08 11:30:52

by Igmar Palsenberg

[permalink] [raw]
Subject: Re: malloc(1/0) ??

On Tue, 7 Nov 2000, Tim Waugh wrote:

> On Wed, Nov 08, 2000 at 01:41:40AM +0100, Igmar Palsenberg wrote:
>
> > malloc(0) is bogus in this case. malloc(0) == free();
>
> No, you're thinking of realloc.

Yep. My error. Sorry.


Igmar

2000-11-08 22:12:24

by H. Peter Anvin

[permalink] [raw]
Subject: Re: malloc(1/0) ??

Followup to: <[email protected]>
By author: Igmar Palsenberg <[email protected]>
In newsgroup: linux.dev.kernel
>
>
> > The program does not work. A program works if it does what it's supposed to
> > do. If you want to argue that this program is supposed to print "ffffff"
> > then explain to me why the 'malloc' contains a zero in parenthesis.
> >
> > The program can't possibly work because it invokes undefined behavior. It
> > is impossible to determine what a program that invokes undefined behavior is
> > 'supposed to do'.
>
> May I remind you guys that a malloc(0) is equal to a free(). There is no
> way that any mem get's malloced.
>

Where the heck did you get idea?

-hpa
--
<[email protected]> at work, <[email protected]> in private!
"Unix gives you enough rope to shoot yourself in the foot."
http://www.zytor.com/~hpa/puzzle.txt

2000-11-08 22:19:14

by Rasmus Andersen

[permalink] [raw]
Subject: Re: malloc(1/0) ??

On Wed, Nov 08, 2000 at 02:11:34PM -0800, H. Peter Anvin wrote:
> Followup to: <[email protected]>
> By author: Igmar Palsenberg <[email protected]>
> In newsgroup: linux.dev.kernel

[snip]

> > May I remind you guys that a malloc(0) is equal to a free(). There is no
> > way that any mem get's malloced.
> >
>
> Where the heck did you get idea?
>
> -hpa

Probably from the malloc man page where it is stated that *realloc*
with size 0 equals free :)
--
Rasmus([email protected])

Which is worse: Ignorance or Apathy?
Who knows? Who cares?

2000-11-09 14:55:58

by Igmar Palsenberg

[permalink] [raw]
Subject: Re: malloc(1/0) ??


> Where the heck did you get idea?

By reading the man page in the middle of the night and reading
realloc() as malloc().

My error.

> -hpa


Igmar