我如何在堆上分配委托?

问题描述 投票:0回答:1

我如何堆分配代表并获得指向它的指针?

我希望能够将其强制转换为void指针并返回,以便可以将其存储在异构数组中。

d
1个回答
0
投票
与动态数组类似,D中的[[a delegate]是具有2个指针字段的简单结构。它具有以下字段:

    .ptr,它是上下文指针(this引用,闭包,堆栈帧指针)
  • .funcptr,它是函数指针
  • 因此,如果您绝对可以确保在调用序列化委托时上下文指针不会被破坏(最好在类this引用上,这通常是类的成员函数),则可以存储一个使用这2个void*值在堆上构造struct或复制其字节,然后将其反序列化回委托。

    示例:

    alias MyDelegate = void delegate(); void main() { int local; MyDelegate dlg = () { import std.stdio; writeln("delegate ", local); }; // T.sizeof always gives the size of what the size is as a struct. // So not the size of what something points to (e.g. class is size_t.sizeof) // Copies the bytes on the stack stored for the delegate, doesn't pin the // context pointer or anything like that which would make it a safer operation auto heap = (cast(ubyte*)&dlg)[0 .. MyDelegate.sizeof].dup.ptr; local = 5; callHeapDlg(heap); } void callHeapDlg(ubyte* heap) { // This could be a potentially unsafe cast if casting to some other delegate! // You might be casting away safety attributes or other things. Best to // restrict the type of the delegate you convert to heap from the start. // Simply recreates the delegate by casting a pointer to the bytes you have // copied to a pointer to a delegate object and then dereferencing it. // This copies the pointers from the heap back to the stack here. auto dlg = *(cast(MyDelegate*) heap[0 .. MyDelegate.sizeof]); dlg(); // prints "delegate 5" }

    但是请永远不要忘记这是一个不安全的操作,您可能会破坏应用程序,甚至不小心引入任意代码执行。特别是如果您的委托上下文指针超出范围并被释放,则可能会遇到严重的不可调试问题。

    例如,在这种情况下,您不应在主函数之外调用分配给堆的委托,因为它很可能包含指向主函数当前堆栈框架的指针,该指针在离开后将变为无效。

    请参见https://dlang.org/spec/abi.html#delegates

  • © www.soinside.com 2019 - 2024. All rights reserved.