This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: strict aliasing question


Howard Chu wrote:
> extern void getit( void **arg );
> 
> main() {
>        union {
>                int *foo;
>                void *bar;
>        } u;
> 
>        getit( &u.bar );
>        printf("foo: %x\n", *u.foo);
> }

Rask Ingemann Lambertsen wrote:
> As far as I know, memcpy() is the answer:

You don't need a union or memcpy() to convert the pointer types.  You can
solve the "void **" aliasing problem with just a cast:

	void *p;
	getit(&p);
	printf("%d\n", *(int *)p);

This assumes that getit() actually writes to an "int" object and returns
a "void *" pointer to that object.  If it doesn't then you have another
aliasing problem to worry about.  If it writes to the object using some
other known type, then you need two casts to make it safe:

	void *p;
	getit(&p);
	printf("%d\n", (int)*(long *)p);

If writes to the object using an unknown type then you might able to
use memcpy() to get around the aliasing problem, but this assumes you
know that two types are compatable at the bit level:

	void *p;
	int n;
	getit(&p);
	memcpy(&n, p, sizeof n);
	printf("%d\n", n);

The best solution would be to fix the interface so that it returns the
pointer types it acutally uses.  This would make it typesafe and you
wouldn't need to use any casts.  If you can't fix the interface itself
the next best thing would be to create your own wrappers which put all
the nasty casts in one place:

	int sasl_getprop_str(sasl_conn_t *conn, int prop, char const **pvalue)
	{
		assert(prop == SASL_AUTHUSER || prop == SASL_APPNAME || ...);
		void *tmp;
		int r = sasl_getprop(conn, prop, &tmp);
		if (r == SASL_OK) 
			*pvalue = (char const *) tmp;
		return r;
	}

Unfortuantely, there are aliasing problems in the Cyrus SASL source that
can still come around and bite you once LTO arrives no matter what you
do in your own code.  You might want to see if you can't get them to
change undefined code like this:

	*(unsigned **)pvalue = &conn->oparams.maxoutbuf;

into code like this:

	*pvalue = (void *) &conn->oparams.maxoutbuf;

					Ross Ridge


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]