call to malloc with size 0

Discussion in 'C Programming' started by Neo, Nov 17, 2004.

  1. Neo

    Neo Guest

    Hi Folks,

    I've a simple qestion related to dynamic memory allocation in C here is the
    code:

    #include <stdio.h>

    int main()

    {

    char *p;

    if( (p=(char*)malloc(0)) == NULL)

    printf("NULL\n");

    else

    printf("Valid Pointer\n");

    return 0;

    }



    Output : "Valid Pointer"

    Why this code fragment returns a valid pointer to a memory block???

    -Neo
     
    Neo, Nov 17, 2004
    #1
    1. Advertising

  2. In article <>,
    says...

    > Why this code fragment returns a valid pointer to a memory block???
    >
    > -Neo


    I've seen this before. Some versions of UNIX will return an error,
    others will return a valid pointer. I'm not sure which is correct but I
    found the 2nd situation to be more common and more useful as you don't
    have to code round it - I've got a few +1's in some code just to
    guarentee a valid pointer which happens to contain nothing. That way I
    know the pointer has been initialised even it doesn't contain anything.
    It's working like a flag as well as a place to store results.

    --
    http://www.beluga.freeserve.co.uk
     
    Peter Smithson, Nov 17, 2004
    #2
    1. Advertising

  3. Neo

    Ravi Uday Guest

    "Neo" <> wrote in message
    news:...
    > Hi Folks,
    >
    > I've a simple qestion related to dynamic memory allocation in C here is

    the
    > code:
    >
    > #include <stdio.h>
    >
    > int main()
    >
    > {
    >
    > char *p;
    >
    > if( (p=(char*)malloc(0)) == NULL)
    >
    > printf("NULL\n");
    >
    > else
    >
    > printf("Valid Pointer\n");
    >
    > return 0;
    >
    > }
    >
    >
    >
    > Output : "Valid Pointer"
    >
    > Why this code fragment returns a valid pointer to a memory block???
    >
    > -Neo
    >
    >

    See what the standard says

    4.10.3 Memory management functions:

    If the size of the space requested is zero, the behavior is
    *implementation-defined*; the value returned shall be either a null
    pointer or a unique pointer.

    So check in your impelementation documents for answer !

    - Ravi



    >
    >
     
    Ravi Uday, Nov 17, 2004
    #3
  4. Neo

    Neo Guest

    "Ravi Uday" <> wrote in message
    news:1100686594.274808@sj-nntpcache-5...
    >
    > "Neo" <> wrote in message
    > news:...
    >> Hi Folks,
    >>
    >> I've a simple qestion related to dynamic memory allocation in C here is

    > the
    >> code:
    >>
    >> #include <stdio.h>
    >>
    >> int main()
    >>
    >> {
    >>
    >> char *p;
    >>
    >> if( (p=(char*)malloc(0)) == NULL)
    >>
    >> printf("NULL\n");
    >>
    >> else
    >>
    >> printf("Valid Pointer\n");
    >>
    >> return 0;
    >>
    >> }
    >>
    >>
    >>
    >> Output : "Valid Pointer"
    >>
    >> Why this code fragment returns a valid pointer to a memory block???
    >>
    >> -Neo
    >>
    >>

    > See what the standard says
    >
    > 4.10.3 Memory management functions:
    >
    > If the size of the space requested is zero, the behavior is
    > *implementation-defined*; the value returned shall be either a null
    > pointer or a unique pointer.
    >
    > So check in your impelementation documents for answer !
    >
    > - Ravi
    >


    O'kay thanks for pointing it out.
    But what should be the suggested behavior and why?
    Is a valid pointer right way?
    I think NULL is a better option? isn't it???

    -Neo
     
    Neo, Nov 17, 2004
    #4
  5. On Wed, 17 Nov 2004 15:49:10 +0530, Ravi Uday wrote:

    >
    > "Neo" <> wrote in message
    > news:...
    >> Hi Folks,
    >>
    >> I've a simple qestion related to dynamic memory allocation in C here is

    > the
    >> code:
    >>
    >> #include <stdio.h>
    >>
    >> int main()
    >>
    >> {
    >>
    >> char *p;
    >>
    >> if( (p=(char*)malloc(0)) == NULL)


    Get rid of the cast. The compiler should then complain, which is
    good because the code is broken. Adding the cast doesn't fix the
    code, it just stops the compiler complaining about the problem.

    The problem is that you don't have a valid declaration for malloc()
    in scope when you call it. In that case the compiler assumes
    that malloc() returns int, but it doesn't, it returns void *. All
    standard library functions are provided with a declaration in
    the appropriate standard header. For malloc() that is <stdlib.h>.

    >>
    >> printf("NULL\n");
    >>
    >> else
    >>
    >> printf("Valid Pointer\n");
    >>
    >> return 0;
    >>
    >> }
    >>
    >>
    >>
    >> Output : "Valid Pointer"
    >>
    >> Why this code fragment returns a valid pointer to a memory block???


    Your code invokes undefined behaviour due to the invalid cast, so anything
    can happen. Once that's fixed the issue is as below i.e. the compiler does
    it because the standard says it can.

    >>
    >> -Neo
    >>
    >>

    > See what the standard says
    >
    > 4.10.3 Memory management functions:
    >
    > If the size of the space requested is zero, the behavior is
    > *implementation-defined*; the value returned shall be either a null
    > pointer or a unique pointer.
    >
    > So check in your impelementation documents for answer !


    Lawrence
     
    Lawrence Kirby, Nov 17, 2004
    #5
  6. Neo

    Method Man Guest

    "Ravi Uday" <> wrote in message
    news:1100686594.274808@sj-nntpcache-5...
    >
    > "Neo" <> wrote in message
    > news:...
    > > Hi Folks,
    > >
    > > I've a simple qestion related to dynamic memory allocation in C here is

    > the
    > > code:
    > >
    > > #include <stdio.h>
    > >
    > > int main()
    > >
    > > {
    > >
    > > char *p;
    > >
    > > if( (p=(char*)malloc(0)) == NULL)
    > >
    > > printf("NULL\n");
    > >
    > > else
    > >
    > > printf("Valid Pointer\n");
    > >
    > > return 0;
    > >
    > > }
    > >
    > >
    > >
    > > Output : "Valid Pointer"
    > >
    > > Why this code fragment returns a valid pointer to a memory block???
    > >
    > > -Neo
    > >
    > >

    > See what the standard says
    >
    > 4.10.3 Memory management functions:
    >
    > If the size of the space requested is zero, the behavior is
    > *implementation-defined*; the value returned shall be either a null
    > pointer or a unique pointer.
    >
    > So check in your impelementation documents for answer !
    >
    > - Ravi
    >


    <OT>

    Why didn't they put it in the standard that a null pointer must be returned?
    It seems like the right/logical behaviour for calling malloc on size 0 and
    avoids any confusion.

    </OT>
     
    Method Man, Nov 17, 2004
    #6
  7. Neo

    Richard Bos Guest

    Peter Smithson <> wrote:

    > In article <>,
    > says...
    >
    > > Why this code fragment returns a valid pointer to a memory block???

    >
    > I've seen this before. Some versions of UNIX will return an error,


    By which, I hope, you mean a null pointer, since causing a segfault or a
    signal for malloc(0) is not conforming.

    > others will return a valid pointer. I'm not sure which is correct


    Either.

    Richard
     
    Richard Bos, Nov 17, 2004
    #7
  8. On Wed, 17 Nov 2004 07:45:50 -0500, Method Man wrote:


    ....

    > <OT>
    >
    > Why didn't they put it in the standard that a null pointer must be returned?
    > It seems like the right/logical behaviour for calling malloc on size 0 and
    > avoids any confusion.
    >
    > </OT>


    Probably because there were existing implementations for both types of
    result. I don't think it makes much practical difference, I can only think
    of 2 uses for this:

    1. Creating a unique pointer value which compares unequal to all others.
    For this to work you would need to prefer the non-null return behaviour.
    Of course you can use malloc(1) for this. However malloc() can always fail
    so it could return null for any call.

    2. You are setting up an object whick you might extend later using
    realloc(). However whether malloc(0) return null or not is immaterial to
    this, either result can be passed to realloc(). So the latitude given by
    the standard is harmless here. Of course you have the issue of freeing the
    "object" for a non-null return.

    Lawrence
     
    Lawrence Kirby, Nov 17, 2004
    #8
  9. Neo

    Richard Bos Guest

    Lawrence Kirby <> wrote:

    > 2. You are setting up an object whick you might extend later using
    > realloc(). However whether malloc(0) return null or not is immaterial to
    > this, either result can be passed to realloc(). So the latitude given by
    > the standard is harmless here. Of course you have the issue of freeing the
    > "object" for a non-null return.


    Even that is not a problem, since free(0) is harmless. No matter what
    you get from malloc(), you can free() it.

    Richard
     
    Richard Bos, Nov 17, 2004
    #9
  10. On Wed, 17 Nov 2004 13:53:09 +0000, Richard Bos wrote:

    > Lawrence Kirby <> wrote:
    >
    >> 2. You are setting up an object whick you might extend later using
    >> realloc(). However whether malloc(0) return null or not is immaterial to
    >> this, either result can be passed to realloc(). So the latitude given by
    >> the standard is harmless here. Of course you have the issue of freeing the
    >> "object" for a non-null return.

    >
    > Even that is not a problem, since free(0) is harmless. No matter what
    > you get from malloc(), you can free() it.


    True, my intent was more along the lines of you have consider calling free()
    appropriately for a non-null return, whereas if the return was always
    null in this case you wouldn't have to worry.

    However given the possibility extending the object to non-zero length
    there's likely to be code to handle freeing anyway, so it probably turns
    out to be a non-issue.

    Lawrence
     
    Lawrence Kirby, Nov 17, 2004
    #10
  11. Neo

    Neo Guest

    "Lawrence Kirby" <> wrote in message
    news:p...
    > On Wed, 17 Nov 2004 15:49:10 +0530, Ravi Uday wrote:
    >
    >>
    >> "Neo" <> wrote in message
    >> news:...
    >>> Hi Folks,
    >>>
    >>> I've a simple qestion related to dynamic memory allocation in C here is

    >> the
    >>> code:
    >>>
    >>> #include <stdio.h>
    >>>
    >>> int main()
    >>>
    >>> {
    >>>
    >>> char *p;
    >>>
    >>> if( (p=(char*)malloc(0)) == NULL)

    >
    > Get rid of the cast. The compiler should then complain, which is
    > good because the code is broken. Adding the cast doesn't fix the
    > code, it just stops the compiler complaining about the problem.
    >
    > The problem is that you don't have a valid declaration for malloc()
    > in scope when you call it. In that case the compiler assumes
    > that malloc() returns int, but it doesn't, it returns void *. All
    > standard library functions are provided with a declaration in
    > the appropriate standard header. For malloc() that is <stdlib.h>.
    >
    >>>
    >>> printf("NULL\n");
    >>>
    >>> else
    >>>
    >>> printf("Valid Pointer\n");
    >>>
    >>> return 0;
    >>>
    >>> }
    >>>
    >>>
    >>>
    >>> Output : "Valid Pointer"
    >>>
    >>> Why this code fragment returns a valid pointer to a memory block???

    >
    > Your code invokes undefined behaviour due to the invalid cast, so anything
    > can happen. Once that's fixed the issue is as below i.e. the compiler does
    > it because the standard says it can.
    >


    invalid cast - what do you mean by saying *invalid cast*. isnt it a standard
    practice to cast the pointer returned by the malloc() to desired type? or
    how then it can be otherwise like:
    p = malloc(0);
    ???

    >>>
    >>> -Neo
    >>>
    >>>

    >> See what the standard says
    >>
    >> 4.10.3 Memory management functions:
    >>
    >> If the size of the space requested is zero, the behavior is
    >> *implementation-defined*; the value returned shall be either a null
    >> pointer or a unique pointer.
    >>
    >> So check in your impelementation documents for answer !

    >
    > Lawrence
     
    Neo, Nov 18, 2004
    #11
  12. Neo wrote:

    > I've a simple qestion related to dynamic memory allocation in C.


    [snip]

    > cat main.c

    #include <stdio.h>
    #include <stdlib.h>

    int main(int argc, char* argv[]) {

    char *p = (char*)malloc(0);

    if(NULL == p)
    printf("NULL\n");
    else
    printf("Valid Pointer\n");

    printf("*((int*)p - 1) = %d\n", *((int*)p - 1));
    printf("p = %p\n", p);
    return EXIT_SUCCESS;
    }

    > gcc -Wall -std=c99 -pedantic -o main main.c
    > ./main

    Valid Pointer
    *((int*)p - 1) = 17
    p = 0x9876008

    My implementation allocates at least two
    double word aligned double words
    and returns a pointer to the second double word.

    > Why this code fragment returns a valid pointer to a memory block?


    Because it can.
     
    E. Robert Tisdale, Nov 18, 2004
    #12
  13. Neo

    pete Guest

    Neo wrote:

    > >>> #include <stdio.h>


    > >>> if( (p=(char*)malloc(0)) == NULL)


    > isnt it a standard
    > practice to cast the pointer returned by the malloc() to desired type?


    No.
    It's a mistake that people make when they neglect to include stdlib.h,
    and the compiler consequently warns them that malloc is returning
    type int and needs to be cast.
    Add
    #include <stdlib.h>
    and drop the cast.

    --
    pete
     
    pete, Nov 18, 2004
    #13
  14. Neo

    Method Man Guest

    "Lawrence Kirby" <> wrote in message
    news:p...
    > On Wed, 17 Nov 2004 07:45:50 -0500, Method Man wrote:
    >
    >
    > ...
    >
    > > <OT>
    > >
    > > Why didn't they put it in the standard that a null pointer must be

    returned?
    > > It seems like the right/logical behaviour for calling malloc on size 0

    and
    > > avoids any confusion.
    > >
    > > </OT>

    >
    > Probably because there were existing implementations for both types of
    > result. I don't think it makes much practical difference, I can only think
    > of 2 uses for this:
    >
    > 1. Creating a unique pointer value which compares unequal to all others.
    > For this to work you would need to prefer the non-null return behaviour.
    > Of course you can use malloc(1) for this. However malloc() can always fail
    > so it could return null for any call.
    >


    Fair enough. Although, I can't immediately see a practical use in obtaining
    a valid pointer from malloc(0). I would be curious to know how the
    implementation handled dereferencing and type-casting for this magical
    pointer.
     
    Method Man, Nov 18, 2004
    #14
  15. Neo

    Neo Guest

    Right, thnx. for pointing it out.
    its workin perfect!
    -Neo

    "pete" <> wrote in message
    news:...
    > Neo wrote:
    >
    >> >>> #include <stdio.h>

    >
    >> >>> if( (p=(char*)malloc(0)) == NULL)

    >
    >> isnt it a standard
    >> practice to cast the pointer returned by the malloc() to desired type?

    >
    > No.
    > It's a mistake that people make when they neglect to include stdlib.h,
    > and the compiler consequently warns them that malloc is returning
    > type int and needs to be cast.
    > Add
    > #include <stdlib.h>
    > and drop the cast.
    >
    > --
    > pete
     
    Neo, Nov 18, 2004
    #15
  16. Neo

    Dan Pop Guest

    In <5g0nd.11347$> "Method Man" <> writes:


    >"Lawrence Kirby" <> wrote in message
    >news:p...
    >> On Wed, 17 Nov 2004 07:45:50 -0500, Method Man wrote:
    >>
    >>
    >> ...
    >>
    >> > <OT>
    >> >
    >> > Why didn't they put it in the standard that a null pointer must be

    >returned?
    >> > It seems like the right/logical behaviour for calling malloc on size 0

    >and
    >> > avoids any confusion.
    >> >
    >> > </OT>

    >>
    >> Probably because there were existing implementations for both types of
    >> result. I don't think it makes much practical difference, I can only think
    >> of 2 uses for this:
    >>
    >> 1. Creating a unique pointer value which compares unequal to all others.
    >> For this to work you would need to prefer the non-null return behaviour.
    >> Of course you can use malloc(1) for this. However malloc() can always fail
    >> so it could return null for any call.
    >>

    >
    >Fair enough. Although, I can't immediately see a practical use in obtaining
    >a valid pointer from malloc(0).


    It's a "cheap" method for generating unique IDs.

    >I would be curious to know how the
    >implementation handled dereferencing and type-casting for this magical
    >pointer.


    The pointer is as ordinary as you can get. Dereferencing it invokes
    undefined behaviour and conversions work as for other pointers. As
    Lawrence told you, if you need this particular behaviour, just use the
    following wrapper for malloc:

    void *xmalloc(size_t size)
    {
    if (size == 0) size = 1;
    return malloc(size);
    }

    And if you need the other behaviour, you can trivially get it from:

    void *ymalloc(size_t size)
    {
    if (size == 0) return NULL;
    return malloc(size);
    }

    Or, if you prefer macros:

    #define XMALLOC(size) malloc(size == 0 ? 1 : size)
    #define YMALLOC(size) (size == 0 ? NULL : malloc(size))

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
    Currently looking for a job in the European Union
     
    Dan Pop, Nov 18, 2004
    #16
  17. Method Man <> scribbled the following:
    > "Lawrence Kirby" <> wrote in message
    > news:p...
    >> On Wed, 17 Nov 2004 07:45:50 -0500, Method Man wrote:
    >> > <OT>
    >> >
    >> > Why didn't they put it in the standard that a null pointer must be

    > returned?
    >> > It seems like the right/logical behaviour for calling malloc on size 0

    > and
    >> > avoids any confusion.
    >> >
    >> > </OT>

    >>
    >> Probably because there were existing implementations for both types of
    >> result. I don't think it makes much practical difference, I can only think
    >> of 2 uses for this:
    >>
    >> 1. Creating a unique pointer value which compares unequal to all others.
    >> For this to work you would need to prefer the non-null return behaviour.
    >> Of course you can use malloc(1) for this. However malloc() can always fail
    >> so it could return null for any call.


    > Fair enough. Although, I can't immediately see a practical use in obtaining
    > a valid pointer from malloc(0). I would be curious to know how the
    > implementation handled dereferencing and type-casting for this magical
    > pointer.


    If the C memory model was continuous rather than discrete, then there
    would be no problem. In a continuous memory model, pointer values would
    only serve as "starting points" of allocated memory, not allocated
    memory itself. If you think of the conventional discrete memory model as
    labelling boxes with addresses, in a continuous memory model you don't
    label the boxes, you label the gaps between them. This way the malloc()
    implementation could safely return the same, non-null, pointer value
    over and over again from calls to malloc(0), because reserving 0 bytes
    onward from that gap between boxes doesn't actually reserve any box at
    all, and it's the boxes you store stuff in, not the gaps between them.
    This is of course very much off-topic for comp.lang.c but those who
    have studied real analysis and topology know what I'm talking about.

    --
    /-- Joona Palaste () ------------- Finland --------\
    \-------------------------------------------------------- rules! --------/
    "It's time, it's time, it's time to dump the slime!"
    - Dr. Dante
     
    Joona I Palaste, Nov 18, 2004
    #17
  18. "Dan Pop" <> wrote in message
    news:cnicom$nda$...
    > In <5g0nd.11347$> "Method Man" <> writes:
    >>Fair enough. Although, I can't immediately see a practical use in
    >>obtaining
    >>a valid pointer from malloc(0).

    >
    > It's a "cheap" method for generating unique IDs.


    Are successive calls to malloc(0) guaranteed to return unique values,
    though? (Assuming they don't return NULL.) Given that actually
    dereferencing such the pointer invokes undefined behaviour, couldn't a
    malloc() implementation set aside a certain value that it always returns
    when size is 0? It might have to increment a reference count that would
    later get decremented by free().
     
    Craig Barkhouse, Nov 18, 2004
    #18
  19. Neo

    Richard Bos Guest

    "Craig Barkhouse" <> wrote:

    > Are successive calls to malloc(0) guaranteed to return unique values,
    > though? (Assuming they don't return NULL.) Given that actually
    > dereferencing such the pointer invokes undefined behaviour, couldn't a
    > malloc() implementation set aside a certain value that it always returns
    > when size is 0?


    In C89, it isn't perfectly clear; the text says that

    # If the space cannot be allocated, a null pointer is returned.
    # If the size of the space requested is zero, the behavior is
    # implementation-defined; the value returned shall be either a null
    # pointer or a unique pointer.

    without clarifying whether that means a pointer unique to zero-sized
    malloc()s, or a unique pointer for _each_ zero-sized malloc().

    In C99, this has been changed to

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

    Since

    # Each such allocation shall yield a pointer to an object disjoint from
    # any other object.

    this means that in C99, each zero-sized malloc() must return a distinct
    pointer (or a null pointer), and I think that with this knowledge, it's
    clear that this was what was meant in C89, too.

    Richard
     
    Richard Bos, Nov 18, 2004
    #19
  20. Neo

    Ben Pfaff Guest

    "Method Man" <> writes:

    > I can't immediately see a practical use in obtaining a valid
    > pointer from malloc(0). I would be curious to know how the
    > implementation handled dereferencing and type-casting for this
    > magical pointer.


    Dereferencing the result of malloc(0) yields undefined behavior.
    What problem do you envision with type-casting it?
    --
    "The way I see it, an intelligent person who disagrees with me is
    probably the most important person I'll interact with on any given
    day."
    --Billy Chambless
     
    Ben Pfaff, Nov 18, 2004
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John
    Replies:
    13
    Views:
    716
  2. ravi
    Replies:
    0
    Views:
    461
  3. Peter
    Replies:
    34
    Views:
    1,993
    Richard Tobin
    Oct 22, 2004
  4. porting non-malloc code to malloc

    , Feb 18, 2005, in forum: C Programming
    Replies:
    3
    Views:
    487
    Walter Roberson
    Feb 19, 2005
  5. Johs32

    to malloc or not to malloc??

    Johs32, Mar 30, 2006, in forum: C Programming
    Replies:
    4
    Views:
    333
    Captain Winston
    Mar 30, 2006
Loading...

Share This Page