Small C "Puzzle"

Discussion in 'C Programming' started by Robert Gamble, Aug 28, 2004.

  1. I was taking a look at some of the C puzzles at:
    http://purana.csa.iisc.ernet.in/~gkumar/cquestions.html and have not had
    any trouble with any of them except for the first one which is reproduced
    below:

    The following C program segfaults of IA-64, but works fine on IA-32.
    int main()
    {
    int* p;
    p = (int*)malloc(sizeof(int));
    *p = 10;
    return 0;
    }
    Why does it happen so?

    Now I know that architecture dependant behavior is off-topic, but I don't
    really see anything wrong with the code (yes, stdlib.h is missing, int
    main(void), and malloc casted, but I don't think this has anything to do
    with the point of the problem). Am I missing something here? I don't
    have access to an IA-64 machine, anyone who does have any insight?

    Thanks,

    Rob Gamble
    Robert Gamble, Aug 28, 2004
    #1
    1. Advertising

  2. Robert Gamble <> wrote:
    > I was taking a look at some of the C puzzles at:
    > http://purana.csa.iisc.ernet.in/~gkumar/cquestions.html and have not had
    > any trouble with any of them except for the first one which is reproduced
    > below:
    >
    > The following C program segfaults of IA-64, but works fine on IA-32.
    > int main()
    > {
    > int* p;
    > p = (int*)malloc(sizeof(int));
    > *p = 10;
    > return 0;
    > }
    > Why does it happen so?


    Did you check to make sure p != NULL ? There may have been a malloc() failure
    for whatever reason.

    --
    Kristofer Pettijohn
    Kristofer Pettijohn, Aug 28, 2004
    #2
    1. Advertising

  3. Robert Gamble <> writes:
    > I was taking a look at some of the C puzzles at:
    > http://purana.csa.iisc.ernet.in/~gkumar/cquestions.html and have not had
    > any trouble with any of them except for the first one which is reproduced
    > below:
    >
    > The following C program segfaults of IA-64, but works fine on IA-32.
    > int main()
    > {
    > int* p;
    > p = (int*)malloc(sizeof(int));
    > *p = 10;
    > return 0;
    > }
    > Why does it happen so?
    >
    > Now I know that architecture dependant behavior is off-topic, but I don't
    > really see anything wrong with the code (yes, stdlib.h is missing, int
    > main(void), and malloc casted, but I don't think this has anything to do
    > with the point of the problem). Am I missing something here? I don't
    > have access to an IA-64 machine, anyone who does have any insight?


    The missing "#include <stdlib.h>" is exactly the problem.

    In the absence of a visible prototype for malloc(), the compiler
    assumes that it returns int. Since int is 32 bits, but the actual
    void* value that malloc() *tries* to return is 64 bits, the result is
    undefined behavior. In this case, the undefined behavior manifests
    itself as returning the low-order (I think) 32 bits of the pointer
    value. Since the high-order bits include non-zero values, this loses
    information. Casting to int* masks the error, and generates an
    invalid pointer value (whose upper half happens to be all-bits-zero).
    Dereferencing the pointer value on the next line causes more undefined
    behavior, which manifests itself as a seg fault.

    It happens to work on IA-32 (more commonly known as x86) because int
    and pointer types are both 32 bits. The phrase "happens to work"
    means that the undefined behavior manifests itself as the program
    doing what you expected it to do. (This is actually worse than what
    happens on the IA-64, since it masks the error.)

    --
    Keith Thompson (The_Other_Keith) <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.
    Keith Thompson, Aug 28, 2004
    #3
  4. Robert Gamble

    CBFalconer Guest

    Robert Gamble wrote:
    >
    > I was taking a look at some of the C puzzles at:
    > http://purana.csa.iisc.ernet.in/~gkumar/cquestions.html and have
    > not had any trouble with any of them except for the first one
    > which is reproduced below:
    >
    > The following C program segfaults of IA-64, but works fine on IA-32.
    > int main()
    > {
    > int* p;
    > p = (int*)malloc(sizeof(int));
    > *p = 10;
    > return 0;
    > }
    > Why does it happen so?
    >
    > Now I know that architecture dependant behavior is off-topic,
    > but I don't really see anything wrong with the code (yes,
    > stdlib.h is missing, int main(void), and malloc casted, but I
    > don't think this has anything to do with the point of the
    > problem). Am I missing something here? I don't have access
    > to an IA-64 machine, anyone who does have any insight?


    Yes it does. Remove the unnecessary cast, which has prevented
    compiler warnings, and #include <stdlib.h>, and the problem should
    go away.

    --
    A: Because it fouls the order in which people normally read text.
    Q: Why is top-posting such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    CBFalconer, Aug 28, 2004
    #4
  5. Robert Gamble

    Mike Wahler Guest

    "Robert Gamble" <> wrote in message
    news:p...
    > I was taking a look at some of the C puzzles at:
    > http://purana.csa.iisc.ernet.in/~gkumar/cquestions.html and have not had
    > any trouble with any of them except for the first one which is reproduced
    > below:
    >
    > The following C program segfaults of IA-64, but works fine on IA-32.
    > int main()
    > {
    > int* p;
    > p = (int*)malloc(sizeof(int));
    > *p = 10;
    > return 0;
    > }
    > Why does it happen so?
    >
    > Now I know that architecture dependant behavior is off-topic, but I don't
    > really see anything wrong with the code (yes, stdlib.h is missing, int
    > main(void), and malloc casted, but I don't think this has anything to do
    > with the point of the problem).


    Actually, it *is* the problem. Although 'malloc()'s return value
    is cast above, it's already too late. Lacking a proper prototype,
    'malloc()' will be assumed to return type 'int'. So the valid
    pointer value has already been corrupted by the conversion to
    type 'int'. Casting this 'int' back to type 'int*' won't bring
    back the original pointer value.(*)

    > Am I missing something here? I don't
    > have access to an IA-64 machine, anyone who does have any insight?
    >
    > Thanks,


    (*) On some platforms/implementations (e.g. Windows), such conversions
    between 'int' and a pointer type are indeed well defined, but not by
    the language.

    I'm not familiar with the 'IA' machines, but apparently the puzzle
    is referring to the fact that trying to convert a pointer to an
    int and back to a pointer will *not* work correctly on those
    platforms.

    -Mike
    Mike Wahler, Aug 28, 2004
    #5
  6. Robert Gamble

    Mike Wahler Guest

    "Keith Thompson" <> wrote in message
    news:...
    > Robert Gamble <> writes:
    > > I was taking a look at some of the C puzzles at:
    > > http://purana.csa.iisc.ernet.in/~gkumar/cquestions.html and have not had
    > > any trouble with any of them except for the first one which is

    reproduced
    > > below:
    > >
    > > The following C program segfaults of IA-64, but works fine on IA-32.
    > > int main()
    > > {
    > > int* p;
    > > p = (int*)malloc(sizeof(int));
    > > *p = 10;
    > > return 0;
    > > }
    > > Why does it happen so?
    > >
    > > Now I know that architecture dependant behavior is off-topic, but I

    don't
    > > really see anything wrong with the code (yes, stdlib.h is missing, int
    > > main(void), and malloc casted, but I don't think this has anything to do
    > > with the point of the problem). Am I missing something here? I don't
    > > have access to an IA-64 machine, anyone who does have any insight?

    >
    > The missing "#include <stdlib.h>" is exactly the problem.
    >
    > In the absence of a visible prototype for malloc(), the compiler
    > assumes that it returns int. Since int is 32 bits, but the actual
    > void* value that malloc() *tries* to return is 64 bits, the result is
    > undefined behavior. In this case, the undefined behavior manifests
    > itself as returning the low-order (I think) 32 bits of the pointer
    > value. Since the high-order bits include non-zero values, this loses
    > information. Casting to int* masks the error, and generates an
    > invalid pointer value (whose upper half happens to be all-bits-zero).
    > Dereferencing the pointer value on the next line causes more undefined
    > behavior, which manifests itself as a seg fault.
    >
    > It happens to work on IA-32 (more commonly known as x86)


    Ah, so I guess I *do* know what an 'IA' machine is. :)
    (In my other post I said I did not.)

    -Mike
    Mike Wahler, Aug 28, 2004
    #6
  7. On Fri, 27 Aug 2004 23:38:11 +0000, Keith Thompson wrote:

    > Robert Gamble <> writes:
    >> I was taking a look at some of the C puzzles at:
    >> http://purana.csa.iisc.ernet.in/~gkumar/cquestions.html and have not had
    >> any trouble with any of them except for the first one which is reproduced
    >> below:
    >>
    >> The following C program segfaults of IA-64, but works fine on IA-32.
    >> int main()
    >> {
    >> int* p;
    >> p = (int*)malloc(sizeof(int));
    >> *p = 10;
    >> return 0;
    >> }
    >> Why does it happen so?
    >>
    >> Now I know that architecture dependant behavior is off-topic, but I don't
    >> really see anything wrong with the code (yes, stdlib.h is missing, int
    >> main(void), and malloc casted, but I don't think this has anything to do
    >> with the point of the problem). Am I missing something here? I don't
    >> have access to an IA-64 machine, anyone who does have any insight?

    >
    > The missing "#include <stdlib.h>" is exactly the problem.
    >
    > In the absence of a visible prototype for malloc(), the compiler
    > assumes that it returns int. Since int is 32 bits, but the actual
    > void* value that malloc() *tries* to return is 64 bits, the result is
    > undefined behavior. In this case, the undefined behavior manifests
    > itself as returning the low-order (I think) 32 bits of the pointer
    > value. Since the high-order bits include non-zero values, this loses
    > information. Casting to int* masks the error, and generates an
    > invalid pointer value (whose upper half happens to be all-bits-zero).
    > Dereferencing the pointer value on the next line causes more undefined
    > behavior, which manifests itself as a seg fault.
    >
    > It happens to work on IA-32 (more commonly known as x86) because int
    > and pointer types are both 32 bits. The phrase "happens to work"
    > means that the undefined behavior manifests itself as the program
    > doing what you expected it to do. (This is actually worse than what
    > happens on the IA-64, since it masks the error.)


    I really did not consider this an option due to the fact that all the
    other examples on the site cast malloc and declare main the same way. I
    did just check though and all of the other examples do include proper
    header files. I was overlooking the obvious thinking that there was a
    deeper issue at work.

    Thanks for the detailed explanation. Another reason I dismissed this as
    my original answer was that I was thinking that int was 64 bits on IA-64
    which did not seem any different from what would be happening on a 32-bit
    machine. I'd forgotten this was not the case with most enviornments until
    I read your post (I don't program on 64-bit machines yet ;)

    I didn't want to beleive this was the answer because it didn't seem as
    clear-cut as the other puzzles, kind of obvious and anti-climactic, but
    you have talked me into it ;)

    Thanks,

    Rob Gamble
    Robert Gamble, Aug 28, 2004
    #7
  8. Robert Gamble

    Jack Klein Guest

    On Fri, 27 Aug 2004 23:38:11 GMT, Keith Thompson <> wrote
    in comp.lang.c:

    > Robert Gamble <> writes:
    > > I was taking a look at some of the C puzzles at:
    > > http://purana.csa.iisc.ernet.in/~gkumar/cquestions.html and have not had
    > > any trouble with any of them except for the first one which is reproduced
    > > below:
    > >
    > > The following C program segfaults of IA-64, but works fine on IA-32.
    > > int main()
    > > {
    > > int* p;
    > > p = (int*)malloc(sizeof(int));
    > > *p = 10;
    > > return 0;
    > > }
    > > Why does it happen so?
    > >
    > > Now I know that architecture dependant behavior is off-topic, but I don't
    > > really see anything wrong with the code (yes, stdlib.h is missing, int
    > > main(void), and malloc casted, but I don't think this has anything to do
    > > with the point of the problem). Am I missing something here? I don't
    > > have access to an IA-64 machine, anyone who does have any insight?

    >
    > The missing "#include <stdlib.h>" is exactly the problem.
    >
    > In the absence of a visible prototype for malloc(), the compiler
    > assumes that it returns int. Since int is 32 bits, but the actual
    > void* value that malloc() *tries* to return is 64 bits, the result is
    > undefined behavior. In this case, the undefined behavior manifests
    > itself as returning the low-order (I think) 32 bits of the pointer
    > value.


    Doesn't make any difference what size int or pointers are. The code
    has undefined behavior because it calls ANY function with a return
    type other than int without a prototype in scope. Period. Size of
    anything irrelevant.

    --
    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/~ajo/docs/FAQ-acllc.html
    Jack Klein, Aug 28, 2004
    #8
  9. Robert Gamble

    Raju Guest

    > > The following C program segfaults of IA-64, but works fine on IA-32.
    > > int main()
    > > {
    > > int* p;
    > > p = (int*)malloc(sizeof(int));
    > > *p = 10;
    > > return 0;
    > > }
    > > Why does it happen so?
    > >
    > > Now I know that architecture dependant ...

    > The missing "#include <stdlib.h>" is exactly the problem.
    >
    > In the absence of a visible prototype for malloc(), the compiler
    > assumes that it returns int. Since int is 32 bits, but the actual
    > void* value that malloc() *tries* to return is 64 bits, the result is
    > undefined behavior. In this case, the undefined behavior manifests
    > itself as returning the low-order (I think) 32 bits of the pointer
    > value. Since the high-order bits include non-zero values, this loses
    > information. Casting to int* masks the error, and generates an
    > invalid pointer value (whose upper half happens to be all-bits-zero).
    > Dereferencing the pointer value on the next line causes more undefined
    > behavior, which manifests itself as a seg fault.
    >
    > It happens to work on IA-32 (more commonly known as x86) because int
    > and pointer types are both 32 bits. The phrase "happens to work"
    > means that the undefined behavior manifests itself as the program
    > doing what you expected it to do. (This is actually worse than what
    > happens on the IA-64, since it masks the error.)


    I am little confused about the explanation.
    I think size of "int" is size of processor register length.
    And malloc retuns 64 bit address and pointer is also 64 bit (whether
    int * or char *) , then where actually the size giving problem.

    And can i know how the code below behaves on both platforms,

    int main()
    {
    char* p;
    p = (char*)malloc(sizeof(char));
    *p = 10;
    return 0;
    }
    Raju, Aug 28, 2004
    #9
  10. Robert Gamble

    Malcolm Guest

    "Raju" <> wrote
    >
    > I am little confused about the explanation.
    > I think size of "int" is size of processor register length.
    > And malloc retuns 64 bit address and pointer is also 64 bit (whether
    > int * or char *) , then where actually the size giving problem.
    >
    > And can i know how the code below behaves on both platforms,
    >
    > int main()
    > {
    > char* p;
    > p = (char*)malloc(sizeof(char));
    > *p = 10;
    > return 0;
    > }
    >


    int *s and char *s are almost always the same size. ints are typically the
    size of data registers, which are commonly but not always the size of
    address registers (and on many architectures a register has a dual use). So
    in early versions of C it was in fact accepted to assign a pointer to an
    int, which is why we have the current problem of prototypes being essential
    to make things work correctly.

    If an int and a pointer are both 64 bits, then the undefined behaviour of
    calling malloc() without a protoype in scope should normally be the
    behaviour the programmer expects. In this case it appears that int was 32
    bits and pointers 64 bits, so the ujndefined beahviour instead manifested
    itself as a crash.
    However there could be problems even if ints and pointers are the same
    width, for instance the act of loading an address into a data register could
    trigger a crash. With undefined behaviour, you just don't know.
    Malcolm, Aug 28, 2004
    #10
  11. Jack Klein <> writes:
    > On Fri, 27 Aug 2004 23:38:11 GMT, Keith Thompson <> wrote
    > in comp.lang.c:

    [...]
    > > In the absence of a visible prototype for malloc(), the compiler
    > > assumes that it returns int. Since int is 32 bits, but the actual
    > > void* value that malloc() *tries* to return is 64 bits, the result is
    > > undefined behavior. In this case, the undefined behavior manifests
    > > itself as returning the low-order (I think) 32 bits of the pointer
    > > value.

    >
    > Doesn't make any difference what size int or pointers are. The code
    > has undefined behavior because it calls ANY function with a return
    > type other than int without a prototype in scope. Period. Size of
    > anything irrelevant.


    You're right, of course. (I did mention later that it's also
    undefined behavior on the IA-32, where int and pointer types are the
    same size, but in the quoted paragraph I inadvertently implied a
    cause-and-effect relationship that doesn't exist.)

    The difference in size does make a difference, in this case, in the
    visible result of the undefined behavior.

    --
    Keith Thompson (The_Other_Keith) <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.
    Keith Thompson, Aug 28, 2004
    #11
  12. (Raju) writes:
    [...]
    > I am little confused about the explanation.
    > I think size of "int" is size of processor register length.
    > And malloc retuns 64 bit address and pointer is also 64 bit (whether
    > int * or char *) , then where actually the size giving problem.


    The size of "int" is whatever the compiler implementer decides it
    should be. On the IA-64 (also known as Itanium), int is 32 bits, and
    pointers are 64 bits. More precisely, these are the sizes chosen by
    the compilers I'm familiar with on IA-64 systems (gcc and Intel's
    compiler under Linux). Note that there's a strong motivation for
    different compilers on the same system to be compatible with each
    other.

    Since the IA-64 is a 64-bit system, it's natural to assume that int
    should be 64 bits, but that would actually cause some problems.
    Currently, the types of the predefined integer types are:

    char 8 bits
    short 16 bits
    int 32 bits
    long 64 bits
    long long 64 bits

    If int were 64 bits, short would be either 16 or 32 bits, leaving a
    gap in the type system. (C99 allows extended integer types, with
    appropriate typedefs in <stdint.h>, but portable code can't yet depend
    on this.)

    > And can i know how the code below behaves on both platforms,
    >
    > int main()
    > {
    > char* p;
    > p = (char*)malloc(sizeof(char));
    > *p = 10;
    > return 0;
    > }


    With the understanding that it's undefined behavior regardless
    of the underlying system:

    On IA-32: no ouput.
    On IA-64: Segmentation fault.

    Here's another program that shows more clearly what's going on:

    #ifdef INCLUDE_STDLIB
    #include <stdlib.h>
    #endif
    #include <stdio.h>
    int main()
    {
    char* p;
    p = (char*)malloc(sizeof(char));
    printf("p = %p\n", p);
    fflush(stdout);
    *p = 10;
    return 0;
    }

    On IA-32, this produces nearly the same output whether INCLUDE_STDLIB
    is defined or not:

    p = 0x8648008

    (The specific address changes for some irrelevant reason.)

    On IA-64, if INCLUDE_STDLIB is not defined, the output is:

    p = 0xc80
    Segmentation fault

    If INCLUDE_STDLIB is defined, the output is:

    p = 0x6000000000000c80

    Of course none if this arises if you just write the code properly in
    the first place: use a "#include <stdlib.h>" directive, and don't cast
    the result of malloc().

    --
    Keith Thompson (The_Other_Keith) <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.
    Keith Thompson, Aug 28, 2004
    #12
  13. >If an int and a pointer are both 64 bits, then the undefined behaviour of
    >calling malloc() without a protoype in scope should normally be the
    >behaviour the programmer expects. In this case it appears that int was 32
    >bits and pointers 64 bits, so the ujndefined beahviour instead manifested
    >itself as a crash.


    The unstated assumption here, which is false, is that the linkage
    conventions for two types of the same size are the same. This is
    often not true. Even on an Intel [3456]86 platform, integers and
    floating point numbers are often (but not always) returned in a
    different place.

    For example, on a 680X0 processor it is quite possible (and logical)
    to return pointers in the a0 register and integers in the d0 register
    and floating point numbers in the top of the stack of the floating-point
    unit. If the return type of the function is not known, the calling
    code may retrieve the return value *FROM THE WRONG PLACE*. No amount
    of casting the result will fix that.

    >However there could be problems even if ints and pointers are the same
    >width, for instance
    >the act of loading an address into a data register could
    >trigger a crash.

    This I would think would be rather unusual. However, loading an
    address register with uninitialized or otherwise arbitrary bit
    patterns is much more likely to cause a crash.

    >With undefined behaviour, you just don't know.


    If you load data from the WRONG register, copying it to the "right"
    register won't help, and the issue that loading crap into a register
    might cause problems is a completely separate problem.

    Gordon L. Burditt
    Gordon Burditt, Aug 28, 2004
    #13
  14. Robert Gamble

    Nudge Guest

    Mike Wahler wrote:

    > I'm not familiar with the 'IA' machines, but apparently the
    > puzzle is referring to the fact that trying to convert a pointer
    > to an int and back to a pointer will *not* work correctly on
    > those platforms.


    AFAIK, IA stands for Intel Architecture.

    Thus IA-32 is Intel's 32-bit ISA, i.e. x86, and IA-64 is Intel's
    64-bit ISA, i.e. the Itanium Processor Family ISA.

    --
    Regards, Nudge
    Nudge, Aug 29, 2004
    #14
  15. Robert Gamble

    Minti Guest

    {OT} Re: Small C "Puzzle"

    "Raju" <> wrote in message
    news:...
    > > > The following C program segfaults of IA-64, but works fine on IA-32.
    > > > int main()
    > > > {
    > > > int* p;
    > > > p = (int*)malloc(sizeof(int));
    > > > *p = 10;
    > > > return 0;
    > > > }
    > > > Why does it happen so?
    > > >
    > > > Now I know that architecture dependant ...

    > > The missing "#include <stdlib.h>" is exactly the problem.
    > >
    > > In the absence of a visible prototype for malloc(), the compiler
    > > assumes that it returns int. Since int is 32 bits, but the actual
    > > void* value that malloc() *tries* to return is 64 bits, the result is
    > > undefined behavior. In this case, the undefined behavior manifests
    > > itself as returning the low-order (I think) 32 bits of the pointer
    > > value. Since the high-order bits include non-zero values, this loses
    > > information. Casting to int* masks the error, and generates an
    > > invalid pointer value (whose upper half happens to be all-bits-zero).
    > > Dereferencing the pointer value on the next line causes more undefined
    > > behavior, which manifests itself as a seg fault.
    > >
    > > It happens to work on IA-32 (more commonly known as x86) because int
    > > and pointer types are both 32 bits. The phrase "happens to work"
    > > means that the undefined behavior manifests itself as the program
    > > doing what you expected it to do. (This is actually worse than what
    > > happens on the IA-64, since it masks the error.)

    >
    > I am little confused about the explanation.
    > I think size of "int" is size of processor register length.
    > And malloc retuns 64 bit address and pointer is also 64 bit (whether
    > int * or char *) , then where actually the size giving problem.




    > And can i know how the code below behaves on both platforms,
    >
    > int main()
    > {
    > char* p;
    > p = (char*)malloc(sizeof(char));
    > *p = 10;
    > return 0;
    > }


    Yup you are right. But you might note that even if a compiler is supporting
    64 bit arch. It will in many cases keep int's to be 32 bit's { to keep
    backward compatiblity for applications written assuming int to be 32 bits }
    That said I think that is just a guess. For I really haven't used any 64 bit
    compilers. Can anyone share the current trends in this 64 bit industry. gcc,
    MS cl etc.



    --
    Imanpreet Singh Arora
    If I would have only known, I would have been a locksmith.
    -- Albert Einstein
    Minti, Aug 29, 2004
    #15
  16. Robert Gamble

    Minti Guest

    "Jack Klein" <> wrote in message
    news:...
    > On Fri, 27 Aug 2004 23:38:11 GMT, Keith Thompson <> wrote
    > in comp.lang.c:
    >
    > > Robert Gamble <> writes:
    > > > I was taking a look at some of the C puzzles at:
    > > > http://purana.csa.iisc.ernet.in/~gkumar/cquestions.html and have not

    had
    > > > any trouble with any of them except for the first one which is

    reproduced
    > > > below:
    > > >
    > > > The following C program segfaults of IA-64, but works fine on IA-32.
    > > > int main()
    > > > {
    > > > int* p;
    > > > p = (int*)malloc(sizeof(int));
    > > > *p = 10;
    > > > return 0;
    > > > }
    > > > Why does it happen so?
    > > >
    > > > Now I know that architecture dependant behavior is off-topic, but I

    don't
    > > > really see anything wrong with the code (yes, stdlib.h is missing, int
    > > > main(void), and malloc casted, but I don't think this has anything to

    do
    > > > with the point of the problem). Am I missing something here? I don't
    > > > have access to an IA-64 machine, anyone who does have any insight?

    > >
    > > The missing "#include <stdlib.h>" is exactly the problem.
    > >
    > > In the absence of a visible prototype for malloc(), the compiler
    > > assumes that it returns int. Since int is 32 bits, but the actual
    > > void* value that malloc() *tries* to return is 64 bits, the result is
    > > undefined behavior. In this case, the undefined behavior manifests
    > > itself as returning the low-order (I think) 32 bits of the pointer
    > > value.

    >
    > Doesn't make any difference what size int or pointers are. The code
    > has undefined behavior because it calls ANY function with a return
    > type other than int without a prototype in scope. Period. Size of
    > anything irrelevant.



    Yes, but the question is why it would work on IA-32 not IA-64. And IA-32 has
    same size and representation specification for pointers and int's alike.


    --
    Imanpreet Singh Arora
    If I would have only known, I would have been a locksmith.
    -- Albert Einstein
    Minti, Aug 30, 2004
    #16
  17. Robert Gamble

    Minti Guest

    "Keith Thompson" <> wrote in message
    news:...
    > (Raju) writes:
    > [...]
    > > I am little confused about the explanation.
    > > I think size of "int" is size of processor register length.
    > > And malloc retuns 64 bit address and pointer is also 64 bit (whether
    > > int * or char *) , then where actually the size giving problem.

    >
    > The size of "int" is whatever the compiler implementer decides it
    > should be. On the IA-64 (also known as Itanium), int is 32 bits, and
    > pointers are 64 bits. More precisely, these are the sizes chosen by
    > the compilers I'm familiar with on IA-64 systems (gcc and Intel's
    > compiler under Linux). Note that there's a strong motivation for
    > different compilers on the same system to be compatible with each
    > other.
    >
    > Since the IA-64 is a 64-bit system, it's natural to assume that int
    > should be 64 bits, but that would actually cause some problems.
    > Currently, the types of the predefined integer types are:
    >
    > char 8 bits
    > short 16 bits
    > int 32 bits
    > long 64 bits
    > long long 64 bits
    >
    > If int were 64 bits, short would be either 16 or 32 bits, leaving a
    > gap in the type system. (C99 allows extended integer types, with
    > appropriate typedefs in <stdint.h>, but portable code can't yet depend
    > on this.)
    >
    > > And can i know how the code below behaves on both platforms,
    > >
    > > int main()
    > > {
    > > char* p;
    > > p = (char*)malloc(sizeof(char));
    > > *p = 10;
    > > return 0;
    > > }

    >
    > With the understanding that it's undefined behavior regardless
    > of the underlying system:
    >
    > On IA-32: no ouput.
    > On IA-64: Segmentation fault.
    >
    > Here's another program that shows more clearly what's going on:
    >
    > #ifdef INCLUDE_STDLIB
    > #include <stdlib.h>
    > #endif
    > #include <stdio.h>
    > int main()
    > {
    > char* p;
    > p = (char*)malloc(sizeof(char));
    > printf("p = %p\n", p);
    > fflush(stdout);
    > *p = 10;
    > return 0;
    > }
    >
    > On IA-32, this produces nearly the same output whether INCLUDE_STDLIB
    > is defined or not:
    >
    > p = 0x8648008
    >
    > (The specific address changes for some irrelevant reason.)
    >
    > On IA-64, if INCLUDE_STDLIB is not defined, the output is:
    >
    > p = 0xc80
    > Segmentation fault
    >
    > If INCLUDE_STDLIB is defined, the output is:
    >
    > p = 0x6000000000000c80
    >
    > Of course none if this arises if you just write the code properly in
    > the first place: use a "#include <stdlib.h>" directive, and don't cast
    > the result of malloc().



    Why not cast? Are you saying this in context with the IA-64 thingy or just
    as a general thingy? I probably have never understood the need to cast or
    not to cast. I seem to consider it to be more of a matter of taste rather
    than anything else now. I have seen lot of debate, Bjarne says use cast,
    everyone here says no.



    --
    Imanpreet Singh Arora
    If I would have only known, I would have been a locksmith.
    -- Albert Einstein
    Minti, Aug 30, 2004
    #17
  18. Minti:

    You e-mailed me a question in response to something I posted on this
    thread. Please post any questions to the newsgroup. If you must send
    me e-mail, don't use a spam-blocked return address. (If kissmyass.com
    is meant to be a spam trap, you should pick a different one; it
    happens to be a real domain, and you could be subjecting its owner to
    spam that was meant for you.)

    In answer to your question, it is never necessary to cast the result
    of malloc() in C; it only masks errors. This is from the latest
    version of the C FAQ (the web version hasn't yet been updated):

    7.7: Why does some code carefully cast the values returned by malloc
    to the pointer type being allocated?

    A: Before ANSI/ISO Standard C introduced the void * generic pointer
    type, these casts were typically required to silence warnings
    (and perhaps induce conversions) when assigning between
    incompatible pointer types.

    Under ANSI/ISO Standard C, these casts are no longer necessary,
    and in fact modern practice discourages them, since they can
    camouflage important warnings which would otherwise be generated
    if malloc() happened not to be declared correctly; see question
    7.6 above. (However, the casts are typically seen in C code
    which for one reason or another is intended to be compatible
    with C++, where explicit casts from void * are required.)

    References: H&S Sec. 16.1 pp. 386-7.

    --
    Keith Thompson (The_Other_Keith) <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.
    Keith Thompson, Aug 30, 2004
    #18
  19. Robert Gamble

    Minti Guest

    "Keith Thompson" <> wrote in message
    news:...
    > Minti:
    >
    > You e-mailed me a question in response to something I posted on this
    > thread. Please post any questions to the newsgroup. If you must send
    > me e-mail, don't use a spam-blocked return address. (If kissmyass.com
    > is meant to be a spam trap, you should pick a different one; it
    > happens to be a real domain, and you could be subjecting its owner to
    > spam that was meant for you.)




    Thanks, my mail program is configured to send both mail and post it to the
    newsgroup, however as a I later checked up after disconnecting that it had
    failed to upload the message. Ooops.


    Thanks. Again.

    --
    Imanpreet Singh Arora
    Isingh A Acm Dot Org
    Minti, Aug 30, 2004
    #19
  20. Robert Gamble

    CBFalconer Guest

    Minti wrote:
    > "Keith Thompson" <> wrote in message
    >

    .... snip ...
    >>
    >> Of course none if this arises if you just write the code properly
    >> in the first place: use a "#include <stdlib.h>" directive, and
    >> don't cast the result of malloc().

    >
    > Why not cast? Are you saying this in context with the IA-64 thingy
    > or just as a general thingy? I probably have never understood the
    > need to cast or not to cast. I seem to consider it to be more of a
    > matter of taste rather than anything else now. I have seen lot of
    > debate, Bjarne says use cast, everyone here says no.


    He is talking about C++. Here we talk about C. They are not the
    same language.

    --
    "Churchill and Bush can both be considered wartime leaders, just
    as Secretariat and Mr Ed were both horses." - James Rhodes.
    "We have always known that heedless self-interest was bad
    morals. We now know that it is bad economics" - FDR
    CBFalconer, Aug 30, 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. Earl Teigrob
    Replies:
    3
    Views:
    6,635
    Nedu N
    Aug 6, 2003
  2. dwa

    Design Puzzle!

    dwa, Jun 10, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    354
    Cowboy \(Gregory A. Beamer\) [MVP]
    Jun 10, 2004
  3. Shankara Narayanan

    Booking puzzle....

    Shankara Narayanan, Jun 17, 2004, in forum: ASP .Net
    Replies:
    20
    Views:
    907
    bredal Jensen
    Jun 30, 2004
  4. VB Programmer
    Replies:
    2
    Views:
    423
    Alan Lambert
    Nov 4, 2004
  5. Minti

    Re: Small C "Puzzle"

    Minti, Aug 31, 2004, in forum: C Programming
    Replies:
    2
    Views:
    286
    CBFalconer
    Aug 31, 2004
Loading...

Share This Page