为何std::ptr::read文档称ptr::copy_nonoverlapping可能触发未定义行为
手动实现swap时copy_nonoverlapping后提前退出触发UB的原因
你的基础认知是正确的:a: &mut T和b: &mut T确实指向两块完全独立的内存空间,文档里提到的「二者引用了相同值」不是指内存地址重叠,而是指两块内存中同时存在逻辑上持有所有权的同一个值的按位拷贝,这种情况会在提前退出时触发UB,具体原因可以按执行顺序拆解:
ptr::read、ptr::copy_nonoverlapping都是纯按位拷贝的底层操作,不会改变原内存的所有权状态,也不会自动调用drop。
- 执行
let tmp = ptr::read(a);之后,a指向的内存中的值已经被按位拷贝到tmp,此时a指向的内存逻辑上处于「无有效所有权值」的状态(相当于值被移动走了,但没有执行drop) - 执行
ptr::copy_nonoverlapping(b, a, 1);时,是把b指向的值按位拷贝一份写入a的内存:- 操作完成后,
a的内存中现在有了一个有效的T类型值,内容和*b完全一致 - 但
b指向的内存中,原来的T类型值仍然是有效的、未被移动的状态
- 操作完成后,
- 如果这一步之后发生panic或者函数提前返回,函数退出后,
a和b对应的外部变量都会被正常执行drop:- 两个内存位置的
T值如果持有堆资源(比如示例中的String),会指向完全相同的底层资源地址 - 相当于同一个堆资源会被释放两次,直接触发未定义行为
- 两个内存位置的
后续的ptr::write(b, tmp)就是为了闭合这个安全漏洞:把原来从a读出来的tmp写入b的内存,直接覆盖b中原有的值拷贝,确保整个函数执行完成后,两个内存位置各持有唯一的有效值,不存在重复的所有权拷贝。
内容的提问来源于stack exchange,提问作者rustyhu
相关产品推荐
相关产品推荐

