469,643 Members | 1,514 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,643 developers. It's quick & easy.

void pointer cast segfaults

I am trying to understand the behavior of void pointers. Can someone
explain to me why I get a segfault for the following program?

#include <stdio.h>

void* plusone(void* i){
int* arg = (int*)i;
int result = (*arg + 1);
return (void*)result;
}
int main(){
void* w1 = (void*)10;
void* result = plusone(w1);
printf("%d", *(int*)result);
}

According to gdb, the cast in the first line of plusone gives the segfault.
Why??

Markus

P.S.: I compiled with gcc 3.2.2
Nov 14 '05 #1
12 5692
Andreas Schmidt wrote:
I am trying to understand the behavior of void pointers.
You're really trying to explain why accessing random addresses
causes your machine to segfault.
Can someone explain to me why I get a segfault for the
following program?

#include <stdio.h>

void* plusone(void* i){
int* arg = (int*)i;
The (int *) cast is unnecessary. But the conversion may fail if the
resulting pointer is not suitably aligned for an int.
int result = (*arg + 1);
You're trying to get an int value from memory you probably don't own.
return (void*)result;
The conversion of an int to a void * is implementation defined.
}
int main(){
void* w1 = (void*)10;
Again the conversion is implementation defined. It is utterly useless
in portable programming because you have _no idea_ what 10 will
represent when converted to a pointer.
void* result = plusone(w1);
printf("%d", *(int*)result);
Again you try and grab an int value from memory you don't own.

Also, without a trailing \n, you have no guarantee of output anyway.
}

According to gdb, the cast in the first line of plusone gives
the segfault.
Why??


What are you actually trying to do? If it is implementation specific,
then ask in an implementation specific newsgroup.

If you're just trying things, then realise that C is probably the
_worst_ language to learn through pure experimentation.

--
Peter

Nov 14 '05 #2
Andreas Schmidt wrote:
Can someone explain to me why I get a segfault for the
following program?

According to gdb, the cast in the first line of plusone
gives the segfault. Why?? #include <stdio.h>

int main(){
void* w1 = (void*)10;
In general, this is illegal: you cannot cast an int to a pointer.
In your case, you will probably end up with a pointer to address
number 10 on your PC.
void* result = plusone(w1);
Now let's look at plusone() (I have rearranged your post a little):
void* plusone(void* i){
int* arg = (int*)i;
You are casting the address 10 to be a pointer to int. This
may also be illegal (for example, on some systems, ints can
only reside at addresses that are a multiple of 4).
int result = (*arg + 1);
This is definitely a problem: you are retrieving an int from
address 10. On a system like Windows XP or Unix or Linux,
you will get a segmentation fault because your program
is not allowed to access address 10 (it can only access
addresses in its own address space).
return (void*)result;
Casting an int to a pointer -- illegal, as I mentioned before.
}
Now we're back to main():
printf("%d", *(int*)result);
Again, dereferencing a pointer to an address you probably
don't own, this will probably give you a segmentation fault.
}
I am trying to understand the behavior of void pointers.


Your code really has nothing to do with void pointers as such,
you could have used int pointers or char pointers and
got the same problems. Generally, you cannot convert between
ints and pointers in this way.

A "void pointer" (or more accurately, a pointer-to-void) is
a pointer where you don't know the type of what it's pointing
to. You can convert other POINTERS into void pointers, and
convert them back again. You can't convert ints etc. into
void pointers.

Here's an example of what you can do:

void plusone(void *ptr)
{
*(int *)ptr += 1;
}

int main()
{
int x = 5;
void *ptr = &x;
plusone(ptr);
printf("%d\n", x);
}

Nov 14 '05 #3
Peter Nilsson wrote:
Andreas Schmidt wrote:
I am trying to understand the behavior of void pointers.
The conversion of an int to a void * is implementation defined.
}
int main(){
void* w1 = (void*)10;


Again the conversion is implementation defined. It is utterly useless
in portable programming because you have _no idea_ what 10 will
represent when converted to a pointer.


I don't think it's utterly useless. The following program works fine:

#include <stdio.h>
int main(){
void* i = (void*)10;
printf("%d\n", (int*)i);
return 0;
}

What do you mean by "implementation specific"? Are you saying I'm just
lucky that it compiles and runs, but it depends on the implementation of
the compiler?


Nov 14 '05 #4
Andreas Schmidt wrote:
The following program works fine:

#include <stdio.h>
int main(){
void* i = (void*)10;
printf("%d\n", (int*)i);
return 0;
}


OK, now I understand I am really just printing the pointer address here...

A.
Nov 14 '05 #5
Andreas Schmidt <sc**********@gmx.de> writes:
Andreas Schmidt wrote:
The following program works fine:

#include <stdio.h>
int main(){
void* i = (void*)10;
printf("%d\n", (int*)i);
return 0;
}


OK, now I understand I am really just printing the pointer address here...


You *might* be printing the address. By using an int* argument with a
"%d" format, you're invoking undefind behavior. (In particular, it's
not uncommon for int and int* to have different sizes.)

--
Keith Thompson (The_Other_Keith) ks***@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.
Nov 14 '05 #6
Andreas Schmidt wrote on 05/05/05 :
#include <stdio.h>

void *plusone (void *i)
{
/* -ed- the value of i is unspecified */

int *arg = (int *) i;
/* -ed- the value of arg is unspecified */

int result = (*arg + 1);
/* -ed- the value of *arg is undefined */

return (void *) result;
/* -ed-
* I'm lost.
* Why in the world are you frankensteining your code like that ?
* Cast is evil, didn't your mom told you that before ?
*/
}

int main (void)
{
/* -ed-
* the result of the conversion of an integer to a pointer constant
* is implementation defined. On my platform, the result is
unspecified.
*
* Using the value of w1 invokes an undefined behaviour.
*/
void *w1 = (void *) 10;

void *result = plusone (w1);
printf ("%d", *(int *) result);
}

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

..sig under repair

Nov 14 '05 #7

"Andreas Schmidt" <sc**********@gmx.de> wrote in message
news:3d***********@individual.net...
I am trying to understand the behavior of void pointers. Can someone
explain to me why I get a segfault for the following program?

#include <stdio.h>

void* plusone(void* i){
int* arg = (int*)i;
int result = (*arg + 1);
return (void*)result; change this to: return (void*)&result;
return the address of result (cast to a void *) [or a pointer to result]
}
int main(){
void* w1 = (void*)10; change this to: void* w1 = (void*)&10;

w1 is assigned the address of 10 (cast to a void *) [or a pointer to
address] void* result = plusone(w1);
printf("%d", *(int*)result);
}

Cian
Nov 14 '05 #8
On Thu, 05 May 2005 09:47:49 +0100, Cian wrote:

"Andreas Schmidt" <sc**********@gmx.de> wrote in message
news:3d***********@individual.net...
I am trying to understand the behavior of void pointers. Can someone
explain to me why I get a segfault for the following program?

#include <stdio.h>

void* plusone(void* i){
int* arg = (int*)i;
int result = (*arg + 1);
return (void*)result; change this to: return (void*)&result;
return the address of result (cast to a void *) [or a pointer to result]
}
int main(){
void* w1 = (void*)10;

change this to: void* w1 = (void*)&10;


10 isn't an lvalue, it is not a valid operand for &. You could change it
to

int value = 10;
void *w1 = &value;
w1 is assigned the address of 10 (cast to a void *) [or a pointer to
address]


Since 10 is not an object or function it has no address.

Lawrence
Nov 14 '05 #9
"Cian" <ci******@REMOVEfastmailTHIS.fm> writes:
void* plusone(void* i){
int* arg = (int*)i;
int result = (*arg + 1);
return (void*)result;

change this to: return (void*)&result;
return the address of result (cast to a void *) [or a pointer to result]


Not a good idea to return a pointer to a local variable.

Jim

--
I was born not knowing and have had only a little time to change
that here and there. -- Richard Feynman
Nov 14 '05 #10
"Old Wolf" <ol*****@inspire.net.nz> writes:
Andreas Schmidt wrote:
Can someone explain to me why I get a segfault for the
following program?

According to gdb, the cast in the first line of plusone
gives the segfault. Why??
#include <stdio.h>

int main(){
void* w1 = (void*)10;


In general, this is illegal: you cannot cast an int to a pointer.


Not quite. C99 6.3.2.3p5 says:

An integer may be converted to any pointer type. Except as
previously specified, the result is implementation-defined, might
not be correctly aligned, might not point to an entity of the
referenced type, and might be a trap representation.

(The "previously specified" refers to null pointer constants.)
In your case, you will probably end up with a pointer to address
number 10 on your PC.


Probably. A footnote says:

The mapping functions for converting a pointer to an integer or an
integer to a pointer are intended to be consistent with the
addressing structure of the execution environment.

Of course, the result is vanishingly unlikely to be useful.

--
Keith Thompson (The_Other_Keith) ks***@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.
Nov 14 '05 #11
On Thu, 05 May 2005 06:25:39 GMT, Keith Thompson <ks***@mib.org>
wrote:
Andreas Schmidt <sc**********@gmx.de> writes:
Andreas Schmidt wrote:
The following program works fine:

#include <stdio.h>
int main(){
void* i = (void*)10;
printf("%d\n", (int*)i);
return 0;
}


OK, now I understand I am really just printing the pointer address here...


You *might* be printing the address. By using an int* argument with a
"%d" format, you're invoking undefind behavior. (In particular, it's
not uncommon for int and int* to have different sizes.)


It also invokes undefined behavior in those cases where the value 10
does not represent the suitably aligned value for the address of an
int.
<<Remove the del for email>>
Nov 14 '05 #12
In article <3d***********@individual.net>,
Andreas Schmidt <sc**********@gmx.de> wrote:
Peter Nilsson wrote:
Andreas Schmidt wrote:
I am trying to understand the behavior of void pointers.

The conversion of an int to a void * is implementation defined.
}
int main(){
void* w1 = (void*)10;


Again the conversion is implementation defined. It is utterly useless
in portable programming because you have _no idea_ what 10 will
represent when converted to a pointer.


I don't think it's utterly useless. The following program works fine:

#include <stdio.h>
int main(){
void* i = (void*)10;
printf("%d\n", (int*)i);
return 0;
}

What do you mean by "implementation specific"? Are you saying I'm just
lucky that it compiles and runs, but it depends on the implementation of
the compiler?


No, you are extremely unlucky.

Luck is when a crappy program crashes on you, giving you the chance the
fix it and may be to learn something.
Nov 14 '05 #13

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

52 posts views Thread by Vladimir Grul | last post: by
16 posts views Thread by He Shiming | last post: by
15 posts views Thread by Stig Brautaset | last post: by
188 posts views Thread by infobahn | last post: by
5 posts views Thread by Stijn van Dongen | last post: by
27 posts views Thread by Erik de Castro Lopo | last post: by
49 posts views Thread by elmar | last post: by
10 posts views Thread by kkirtac | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.