背景
在rust中,async函数会生成一个Future(状态机、无栈协程)。而这个Future默认是实现!Unpin trait
的,主要是避免生成状态机时产生的自引用问题——如果一个结构体包含自引用,那么对它的move很容易造成悬空指针问题(野指针)。
问题
现在的问题是,许多场景是需要将Future移动到堆上,以方便生命周期管理及数据共享。但如果假设一个async函数默认生成的Future分配在栈上,那么再将其通过Box::new等分配到堆上,那么很大概率会导致悬空指针问题。rust是如何允许这种情况存在的呢?
豆包解释
通过和豆包的多轮沟通,大致理解rust的处理方式:即如果一个async函数被Box::pin
调用(或一些其它方式),在编译时会自动将async函数生成的Future分配到堆上。同时其解释Future开始时分配在栈上,但等到被move到堆上时,编译器会自动更新自引用的指向。
结论
开发者可以通过rust的一些语法来决定async函数生成的Future在编译时被分配在堆上还是栈上