digitalmars.D.bugs - [Issue 1648] New: Casting a function literal to void* swallows the function or segfaults
- d-bugmail puremagic.com (21/21) Nov 08 2007 http://d.puremagic.com/issues/show_bug.cgi?id=1648
- d-bugmail puremagic.com (6/6) Nov 08 2007 http://d.puremagic.com/issues/show_bug.cgi?id=1648
- Jarrett Billingsley (10/35) Nov 08 2007 delegate.sizeof != (void*).sizeof.
- Christopher Wright (7/53) Nov 08 2007 (delegate*).sizeof == (void*).sizeof
- Jarrett Billingsley (11/13) Nov 08 2007 Ah, looking at your code again, I realize that I was wrong in reading it...
- d-bugmail puremagic.com (10/10) Nov 08 2007 http://d.puremagic.com/issues/show_bug.cgi?id=1648
- Derek Parnell (41/53) Nov 08 2007 I made a slight change to the code and it seems to work. The 'send' memb...
- Derek Parnell (35/36) Nov 08 2007 Another change to make it clearer to read...
- Jarrett Billingsley (6/30) Nov 09 2007 That works, but you still have to make sure that you don't return from t...
http://d.puremagic.com/issues/show_bug.cgi?id=1648 Summary: Casting a function literal to void* swallows the function or segfaults Product: D Version: 2.007 Platform: PC OS/Version: Linux Status: NEW Severity: normal Priority: P2 Component: DMD AssignedTo: bugzilla digitalmars.com ReportedBy: dhasenan gmail.com When saving a delegate as a void* and only using one delegate from the same function, attempts to execute the delegate by casting to the original type do nothing. When saving multiple delegates from the same function, if any of them are cast to void*, a segmentation fault occurs. Casting is inherently dangerous, I know, but there's no other way to pass a delegate while ignoring its type. --
Nov 08 2007
http://d.puremagic.com/issues/show_bug.cgi?id=1648 ------- Comment #1 from dhasenan gmail.com 2007-11-08 08:04 ------- Created an attachment (id=204) --> (http://d.puremagic.com/issues/attachment.cgi?id=204&action=view) a test case that shows the problem --
Nov 08 2007
<d-bugmail puremagic.com> wrote in message news:bug-1648-3 http.d.puremagic.com/issues/...http://d.puremagic.com/issues/show_bug.cgi?id=1648 Summary: Casting a function literal to void* swallows the function or segfaults Product: D Version: 2.007 Platform: PC OS/Version: Linux Status: NEW Severity: normal Priority: P2 Component: DMD AssignedTo: bugzilla digitalmars.com ReportedBy: dhasenan gmail.com When saving a delegate as a void* and only using one delegate from the same function, attempts to execute the delegate by casting to the original type do nothing. When saving multiple delegates from the same function, if any of them are cast to void*, a segmentation fault occurs. Casting is inherently dangerous, I know, but there's no other way to pass a delegate while ignoring its type. --delegate.sizeof != (void*).sizeof. It's no real surprise that this doesn't work. Delegates are not simple pointers; they are actually a struct with two members, but you shouldn't really be relying on the underlying implementation in any way. What is it that you're trying to do, anyway? Delegates are strongly typed for a reason -- the compiler can't generate the correct call sequence unless it knows the exact type of the delegate. There's probably a much better way of doing what you want.
Nov 08 2007
Jarrett Billingsley wrote:<d-bugmail puremagic.com> wrote in message news:bug-1648-3 http.d.puremagic.com/issues/...(delegate*).sizeof == (void*).sizeof The example casted the address of the delegate to void*. I tried using Variant.coerce to retrieve a boxed delegate, but that failed (delegates aren't numeric types, objects, or strings, and coerce only supports those). Now I've found that Variant.peek does support delegates, so I'm set.http://d.puremagic.com/issues/show_bug.cgi?id=1648 Summary: Casting a function literal to void* swallows the function or segfaults Product: D Version: 2.007 Platform: PC OS/Version: Linux Status: NEW Severity: normal Priority: P2 Component: DMD AssignedTo: bugzilla digitalmars.com ReportedBy: dhasenan gmail.com When saving a delegate as a void* and only using one delegate from the same function, attempts to execute the delegate by casting to the original type do nothing. When saving multiple delegates from the same function, if any of them are cast to void*, a segmentation fault occurs. Casting is inherently dangerous, I know, but there's no other way to pass a delegate while ignoring its type. --delegate.sizeof != (void*).sizeof. It's no real surprise that this doesn't work. Delegates are not simple pointers; they are actually a struct with two members, but you shouldn't really be relying on the underlying implementation in any way. What is it that you're trying to do, anyway? Delegates are strongly typed for a reason -- the compiler can't generate the correct call sequence unless it knows the exact type of the delegate. There's probably a much better way of doing what you want.
Nov 08 2007
"Christopher Wright" <dhasenan gmail.com> wrote in message news:fgve35$eet$1 digitalmars.com...(delegate*).sizeof == (void*).sizeof The example casted the address of the delegate to void*.Ah, looking at your code again, I realize that I was wrong in reading it. Now I notice that it's just plain wrong: void send (void delegate () func) { _funcptr = cast(void*)&func; } This is entirely wrong. You're storing the address of a local variable in a class member, and then trying to call that in another function. A quality compiler would give a warning/error on this, as it's an escaping reference to a local variable.
Nov 08 2007
http://d.puremagic.com/issues/show_bug.cgi?id=1648 dhasenan gmail.com changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED Resolution| |INVALID ------- Comment #3 from dhasenan gmail.com 2007-11-08 17:14 ------- As Jarrett Billingsley pointed out, the error was in my code: taking the address of a local variable. --
Nov 08 2007
On Thu, 8 Nov 2007 23:14:59 +0000 (UTC), d-bugmail puremagic.com wrote:http://d.puremagic.com/issues/show_bug.cgi?id=1648 dhasenan gmail.com changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED Resolution| |INVALID ------- Comment #3 from dhasenan gmail.com 2007-11-08 17:14 ------- As Jarrett Billingsley pointed out, the error was in my code: taking the address of a local variable.I made a slight change to the code and it seems to work. The 'send' member function now receives the address of the delegate rather than the delegate itself. ------------- import std.stdio; class Foo { private void* _funcptr; private void delegate() _func; void send (void delegate ()* func) { _funcptr = cast(void*)func; } void sendTyped (void delegate () func) { _func = func; } void execute () { auto func = *cast(void delegate ()*) _funcptr; func(); } void executeTyped () { _func(); } } void main () { Foo foo = new Foo(); // The following does nothing: auto func = { writefln("greetings"); }; foo.send(&func); foo.execute(); /* Uncommenting the following lines produces a segfault. Commenting the preceding lines and uncommenting the following produces the expected output. */ foo.sendTyped({ writefln("this one is typed"); }); foo.executeTyped(); } ----------- -- Derek (skype: derek.j.parnell) Melbourne, Australia 9/11/2007 10:46:28 AM
Nov 08 2007
On Fri, 9 Nov 2007 10:48:15 +1100, Derek Parnell wrote:I made a slight change to the code and it seems to work.Another change to make it clearer to read... ------------ import std.stdio; class Foo { alias void delegate() dg; private dg* _funcptr; private dg _func; void send (dg* func) { _funcptr = func; } void send (dg func) { _func = func; _funcptr = &_func; } void execute () { (*_funcptr)(); } } void main () { Foo foo = new Foo(); auto func = { writefln("greetings"); }; foo.send(&func); foo.execute(); foo.send({ writefln("this one is typed"); }); foo.execute(); } ---------- -- Derek (skype: derek.j.parnell) Melbourne, Australia 9/11/2007 10:59:25 AM
Nov 08 2007
"Derek Parnell" <derek nomail.afraid.org> wrote in message news:1pvgn2j8ihvm$.1tg724zepcfnz.dlg 40tude.net...import std.stdio; class Foo { alias void delegate() dg; private dg* _funcptr; private dg _func; void send (dg* func) { _funcptr = func; } void send (dg func) { _func = func; _funcptr = &_func; } void execute () { (*_funcptr)(); } } void main () { Foo foo = new Foo(); auto func = { writefln("greetings"); }; foo.send(&func); foo.execute(); foo.send({ writefln("this one is typed"); }); foo.execute(); }That works, but you still have to make sure that you don't return from the function that called foo.send before calling foo.execute (assuming that all this doesn't necessarily happen in main). If you made 'func' static, it'd be fine.
Nov 09 2007