Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Small C "Puzzle" (http://www.velocityreviews.com/forums/t435034-small-c-puzzle.html)

Robert Gamble 08-27-2004 11:29 PM

Small C "Puzzle"
 
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

Kristofer Pettijohn 08-27-2004 11:32 PM

Re: Small C "Puzzle"
 
Robert Gamble <rob_gamble99@hotmail.com> 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@cybernetik.net

Keith Thompson 08-27-2004 11:38 PM

Re: Small C "Puzzle"
 
Robert Gamble <rob_gamble99@hotmail.com> 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) kst-u@mib.org <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.

CBFalconer 08-28-2004 01:19 AM

Re: Small C "Puzzle"
 
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?



Mike Wahler 08-28-2004 01:45 AM

Re: Small C "Puzzle"
 

"Robert Gamble" <rob_gamble99@hotmail.com> wrote in message
news:pan.2004.08.27.23.29.21.904326@hotmail.com...
> 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 08-28-2004 01:46 AM

Re: Small C "Puzzle"
 

"Keith Thompson" <kst-u@mib.org> wrote in message
news:ln8yc05ezg.fsf@nuthaus.mib.org...
> Robert Gamble <rob_gamble99@hotmail.com> 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



Robert Gamble 08-28-2004 01:51 AM

Re: Small C "Puzzle"
 
On Fri, 27 Aug 2004 23:38:11 +0000, Keith Thompson wrote:

> Robert Gamble <rob_gamble99@hotmail.com> 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

Jack Klein 08-28-2004 01:53 AM

Re: Small C "Puzzle"
 
On Fri, 27 Aug 2004 23:38:11 GMT, Keith Thompson <kst-u@mib.org> wrote
in comp.lang.c:

> Robert Gamble <rob_gamble99@hotmail.com> 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/~a...FAQ-acllc.html

Raju 08-28-2004 08:12 AM

Re: Small C "Puzzle"
 
> > 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;
}

Malcolm 08-28-2004 08:28 AM

Re: Small C "Puzzle"
 

"Raju" <g_satyamohanraju@yahoo.co.in> 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.




All times are GMT. The time now is 04:50 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.