Is void* compatible with function pointers?

H. S. Teoh via Digitalmars-d digitalmars-d at puremagic.com
Tue Jun 24 09:55:09 PDT 2014


On Tue, Jun 24, 2014 at 11:36:26AM -0400, Steven Schveighoffer via Digitalmars-d wrote:
> On Tue, 24 Jun 2014 00:24:50 -0400, deadalnix <deadalnix at gmail.com> wrote:
[...]
> >Anything that JIT is affected. Consider the pseudocode:
> >
> >void JIT() {
> >     void* code = malloc(XXX);
> >     // Write instructions into the allocated chunk of memory.
> >
> >     membar(); // Memory barrier to avoid reordering.
> >
> >     auto fun = cast(void function()) code;
> >     fun(); // Even if your codegen is correct, anything can happen this point.
> >}
> 
> This is not what we are talking about.
> 
> We are talking about whether a valid function pointer can be cast to
> void * and back again. It is undefined for C/C++. Should it be defined
> for D?
[...]

It's a judgment call. Defining it means that (void*).sizeof must be the
size of the largest pointer type on a particular platform, meaning that
if, for example, pointer to data is 32-bit but pointer to function is
64-bit, then we're effectively doubling the size of void* (it must be
64-bit to support free casting to/from function pointers) relative to
any other non-function pointer. So code that deals only with data void*
will have to pay for this cost for no benefit.

Having said that, though, I have my doubts as to how significant this
issue is -- almost all modern platforms that I'm aware of have equal
pointer sizes for code and data alike -- it's just so much easier to
make them uniform size; it makes compilers and linkers easier to
implement, and runtime loaders easier to write, etc., not to mention
simplifying CPU design (no need for two separate address decoders to
deal with code vs. data, use uniform instruction formats for accessing
code/data, etc.).

OTOH, perhaps the correct solution is for the user to handle this by
using a union, thus guaranteeing that there will be no platform
dependent issues (you can even throw delegates in there and it will work
correctly, whereas currently, casting a delegate to void* definitely
won't work properly):

	union GenericPtr
	{
		void* data;
		void function(void) funcptr;
		void delegate(void) dg;
	}

	void func() {}
	int x;
	GenericPtr.data = &x;
	GenericPtr.funcptr = &func;
	GenericPtr.dg = () { do_something(); };
	... // etc.


T

-- 
"Holy war is an oxymoron." -- Lazarus Long


More information about the Digitalmars-d mailing list