You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

传递Bytes至函数引发生命周期错误的原因及修复方案

Rust Bytes生命周期错误分析与修复

问题场景

调用方代码(send_msg函数)

pub async fn send_msg(online_users: Arc<Mutex<OnlineUsers>>, msg: &Message, from: &str) -> io::Result<()> {
    let target_user = msg.args.get(0).ok_or(io::Error::from(io::ErrorKind::InvalidInput))?;
    if let Content::Text(ref text) = msg.content {
        let text_owned = text.clone();
        let text_byte = Bytes::from(text_owned.as_bytes());
        let mut online_users = online_users.lock().await;
        online_users.send_to_user(target_user, text_byte).await; 
    }
    Ok(())
}

被调用方代码(send_to_user函数)

pub async fn send_to_user(&mut self, name: &str, content: Bytes) -> io::Result<()> {
    let target_user = self
        .list
        .get_mut(name)
        .ok_or(io::Error::new(io::ErrorKind::NotConnected, name.clone()))?;
    target_user.send(content).await?;
    Ok(())
}

错误信息

error[E0597]: `text_owned` does not live long enough
  --> server/src/handler.rs:28:37
   |
28 |         let text_byte = Bytes::from(text_owned.as_bytes());
   |                         ------------^^^^^^^^^^^^^^^^^^^^^-
   |                         |           |
   |                         |           borrowed value does not live long enough
   |                         argument requires that `text_owned` is borrowed for `'static`
...
31 |     }
   |     - `text_owned` dropped here while still borrowed

问题成因

  • 调用Bytes::from(text_owned.as_bytes())时,as_bytes()返回的&[u8]生命周期与text_owned绑定。Bytes::from针对&[u8]的实现会创建一个引用型Bytes,该Bytes内部持有原切片的引用,因此要求原切片的生命周期必须为'static——否则当text_owned被销毁后,Bytes内部的引用会变成悬垂引用。
  • 常见误解是认为await会保证text_owned存活到send_to_user执行完毕,但Rust的生命周期检查是编译期静态分析,不会考虑运行时的执行顺序。编译器仅能看到text_owned在代码块结束时被销毁,而text_byte(持有对它的引用)可能在其销毁后仍存在,因此触发生命周期错误。

修复方法

方法1:直接从String创建Bytes(推荐,零成本)

Bytes支持直接从String创建,此时会接管String的底层内存,无需复制数据,也不再依赖原String的生命周期:

pub async fn send_msg(online_users: Arc<Mutex<OnlineUsers>>, msg: &Message, from: &str) -> io::Result<()> {
    let target_user = msg.args.get(0).ok_or(io::Error::from(io::ErrorKind::InvalidInput))?;
    if let Content::Text(ref text) = msg.content {
        let text_owned = text.clone();
        let text_byte = Bytes::from(text_owned); // 直接转移String所有权到Bytes
        let mut online_users = online_users.lock().await;
        online_users.send_to_user(target_user, text_byte).await?; // 补充错误处理
    }
    Ok(())
}

方法2:复制切片内容到Bytes

如果不想转移String的所有权,可以使用Bytes::copy_from_slice将切片内容复制到Bytes的内部内存中,生成一个独立的Bytes实例:

pub async fn send_msg(online_users: Arc<Mutex<OnlineUsers>>, msg: &Message, from: &str) -> io::Result<()> {
    let target_user = msg.args.get(0).ok_or(io::Error::from(io::ErrorKind::InvalidInput))?;
    if let Content::Text(ref text) = msg.content {
        let text_byte = Bytes::copy_from_slice(text.as_bytes()); // 复制切片内容
        let mut online_users = online_users.lock().await;
        online_users.send_to_user(target_user, text_byte).await?;
    }
    Ok(())
}

内容的提问来源于stack exchange,提问作者realzhujunhao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 21:21:48