![]() |
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 |
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 |
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. |
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? |
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 |
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 |
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 |
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 |
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; } |
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 10:19 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.