如何使用与线程静态寿命?

问题描述 投票:8回答:2

我目前正在挣扎寿命鲁斯特(1.0),特别是当它通过渠道来传递结构。

我将如何得到这个简单的例子来编译:

use std::sync::mpsc::{Receiver, Sender};
use std::sync::mpsc;
use std::thread::spawn;
use std::io;
use std::io::prelude::*;

struct Message<'a> {
    text: &'a str,
}

fn main() {
    let (tx, rx): (Sender<Message>, Receiver<Message>) = mpsc::channel();

    let _handle_receive = spawn(move || {
        for message in rx.iter() {
            println!("{}", message.text);
        }
    });

    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let message = Message {
            text: &line.unwrap()[..],
        };
        tx.send(message).unwrap();
    }
}

我得到:

error[E0597]: borrowed value does not live long enough
  --> src/main.rs:23:20
   |
23 |             text: &line.unwrap()[..],
   |                    ^^^^^^^^^^^^^ does not live long enough
...
26 |     }
   |     - temporary value only lives until here
   |
   = note: borrowed value must be valid for the static lifetime...

我可以看到这是为什么(line只活了for的一次迭代),但我不能找出这样做的正确的方式是。

  • 我应该,因为编译器的提示,请尝试将&str转换成&'static str
  • 我是否泄漏内存,如果每条线将有一个'static一辈子?
  • 当我应该这样用'static?它说的是,我应该尽量避免或者是完全确定?
  • 有没有通过渠道结构传递Strings的更好的办法?

我对那些幼稚的问题表示歉意。我花了相当长的一段时间了搜索,但我不能完全换我的头周围。这也可能是我的动态语言背景的方式获得:)

顺便说一句:被认为&input[..]String转换成&str OK?这是我能找到这样做的唯一稳定的方式。

rust channel lifetime-scoping
2个回答
12
投票

您不能转换成&'a T除了&'static T通过内存泄漏。幸运的是,这是没有必要的。没有任何理由借用指针发送到线,并保持线的主线程上。你不需要在主线程上线。只需发送线本身,即发送String

如果从多个线程访问是必要的(你不想克隆),使用Arc<String>(在未来,Arc<str>也可以工作)。这样的字符串线程之间共享,正确共享,这样当没有线程使用它了它会准确地释放。

线程之间发送非'static引用是不安全的,因为你永远不知道其他线程多长时间不停地使用,所以当借用到期和物体可以释放你不知道。需要注意的是作用域线程不存在这个问题(这是不是在1.0,但在我们发言被重新设计)确实允许这一点,但有规律,spawned线程做。

'static是不是你应该避免的,这是它做什么完美的罚款:表示此数值为生活在程序运行的整个持续时间。但是,如果这是不是你想传达什么,当然是错误的工具。


0
投票

想想这样说:一个线程有没有语法寿命,即线程不会在创建它的代码块的结尾被丢弃。无论您的数据发送到线程,你必须确保它只要线程做直播,这意味着永远。这意味着'static

有什么可以去错在你的情况,如果是主循环发送到线程的引用并销毁字符串之前它已经被线程处理。用字符串处理时,该线程将访问无效的内存。

一个办法是把你的行成一些静态分配的容器,但是这将意味着你永远无法摧毁这些字符串。一般来说一个坏主意。另一种选择是认为:没有主线程实际需要的线一旦读?如果主线程转移到处理线程行的责任?

struct Message {
    text: String,
}
for line in stdin.lock().lines() {
    let message = Message {
        text: line.unwrap(),
    };
    tx.send(message).unwrap();
}

现在你把从主线程处理器线程所有权(移动)。因为你移动你的价值,任何引用,并参与终身没有检查将不再适用。

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