https://tyrchen.github.io/rust-training/
跟C互操作时,加上上面图片的宏,rust会根据你的各个域的内存的占用自动去调整内存中的位置,让你的内存占用是最优的,而且rust在生成数据结构的结构的时候,它会做一些padding,然后这些padding是为了具有更好的performance,但是这样就会对结构体做一些顺序上的调整,以及加一些padding.
函数的话,如果你看rust生成的assembly code的话,所有的函数都被转换为一个奇奇怪怪的名字,所以在rust里面,如果想跟C互操作的话,对于函数需要加上#[no_mangle],不要去做函数的混淆,data struct 需要做一个repr(C)
使用unsafe还有个好处就是,当你的代码有内存泄露或者有concurrency issue的时候,你马上就知道从哪里去着手,去看问题的所在。相对于C、C++的项目出现这样一个问题,可能是大海捞针,得到处去找问题的根源,而这个问题的根源在大型C、C++项目里面是非常难找的。
有了unsafe之后,如果出现上述问题,肯定就是unsafe代码里面。
函数A call 函数B ,会给函数B生成一个新的frame,然后把一些信息填进去,比说函数A的return Address放进去,然后把这些栈帧都保留进去,然后给函数B传的参数push进去,因为编译器在编译期就知道函数B都用了哪些局部变量,这些局部变量的大小是什么,然后为这些局部变量reserve好这个栈。
一个frame一个frame去压栈。最后return的时候,一个frame一个frame的返回。
上图是单线程里面。总是可以的
但是如果是多线程,如下,就可能有问题了
T1 call一个函数,这个函数生成一个新的thread,然后这个thread把ptr move到新的thread下面。当这种情况发生的时候,compiler就没办法区别了。lifetime没有单线程的那么清晰,因为T1随时可能会结束,T1结束的时候,那么T2里面的ptr指向T1之前的那个有效内存,这个时候栈已经走了,栈走了再引用栈上的数据是非常危险的,因为已经不知道数据时什么样子的了。
</