< 返回版块

sunnyregion 发表于 2021-07-09 15:56

#[tokio::main]
async fn main() -> core::result::Result<(), Box<dyn std::error::Error>> {
    let conf = Ini::load_from_file("conf/appconf.ini")?;
    let sec =conf.section(Some("Vendor"));
    let mut url="";
   match sec.as_ref(){
       Some(x)=>{
           println!("{:?}",x.get("url").unwrap());
           url=x.get("url").unwrap();
       },
       None => {},
   }
……
Ok(())
}

Cargo.toml

[dependencies]
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
rust-ini = "0.17"
73  |     let sec = conf.section(Some("Vendor"));
    |               ^^^^ borrowed value does not live long enough
74  |     let mut url: &'static str ="";
    |                  ------------ type annotation requires that `conf` is borrowed for `'static`
...
115 | }
    | - `conf` dropped here while still borrowed

改成下面的这样

 let conf = Ini::load_from_file("conf/appconf.ini").unwrap();
 let sec=conf.section(Some("Vendor")).unwrap();
 let url=sec.get("url").unwrap();

错误依然

73  |     let sec=conf.section(Some("Vendor")).unwrap();
    |             ^^^^------------------------
    |             |
    |             borrowed value does not live long enough
    |             argument requires that `conf` is borrowed for `'static`
...
117 | }
    | - `conf` dropped here while still borrowed

评论区

写评论
作者 sunnyregion 2021-07-15 18:16

感谢,验证成功

--
👇
Bai-Jinlin: 下面的伙计们,他这个问题和跨线程没有一点关系,就算不用tokio也是错的,因为url变量类型自动推断成了&'static str,下面赋值的还是conf这个生命周期不是static变量里的东西,所以肯定就报错,只要给url加上不是static的类型注释就行了,不过这个例子最好还是把url整成String的。

#[tokio::main]
async fn main() {
    let conf=Ini::load_from_file("test.ini").unwrap();
    let mut url: &str = "";
    if let Some(s)=conf.section(Some("Section1")){
        url = s.get("name").unwrap();
    }
    println!("{}", url);
}
Bai-Jinlin 2021-07-15 10:24

下面的伙计们,他这个问题和跨线程没有一点关系,就算不用tokio也是错的,因为url变量类型自动推断成了&'static str,下面赋值的还是conf这个生命周期不是static变量里的东西,所以肯定就报错,只要给url加上不是static的类型注释就行了,不过这个例子最好还是把url整成String的。

#[tokio::main]
async fn main() {
    let conf=Ini::load_from_file("test.ini").unwrap();
    let mut url: &str = "";
    if let Some(s)=conf.section(Some("Section1")){
        url = s.get("name").unwrap();
    }
    println!("{}", url);
}
aariety 2021-07-15 02:31
更正
  1. 第一段中“因为新线程的存活时间可能比主线程长”这句话是错误的。Rust 中,在主线程运行完成后,会直接结束掉整个进程,而不会等待未完成的线程。因此,正确的解释应该是:因为新线程的存活时间可能比创建新线程的线程长,所以为了安全,在线程间传递非 'static 引用不是 safe 的。

  2. 最后一段中“你必须手动保证新线程在主线程之前结束”更正为“你必须手动保证新线程在当前线程之前结束”。

新增

标准库 nightly 中的 std::thread::Builder::spawn_unchecked 方法也是备选方案之一。但该方法是 unsafe 的,因此仍然需要手动保证安全性。

--
👇
aariety: 你是不是后面把 url 传到其他线程去了?能在线程间安全传递的引用只能是 'static 引用,因为新线程的存活时间可能比主线程长;而这个 url 的生命周期与 conf 是相同的,即与主线程一样长,传到其他线程是不安全的。

就此问题而言,我认为最好的解决办法是用 to_string 复制一下字符串再使用。

也有其他的解决方法,比如使用第三方库,其中比较典型的是 crossbeam 库的 scope() 方法。使用该方法可以让你传递一个引用到新线程。它会阻塞主线程,直到新线程全部完成,因此传递引用是安全的。

或者你可以直接使用 std::mem::transmute()url 的生命周期改成 'static。但是,使用该方式必须小心,你必须手动保证新线程在主线程之前结束。

作者 sunnyregion 2021-07-14 11:22

感谢,我觉着您说的有道理

--
👇
aariety: 你是不是后面把 url 传到其他线程去了?能在线程间安全传递的引用只能是 'static 引用,因为新线程的存活时间可能比主线程长;而这个 url 的生命周期与 conf 是相同的,即与主线程一样长,传到其他线程是不安全的。

就此问题而言,我认为最好的解决办法是用 to_string 复制一下字符串再使用。

也有其他的解决方法,比如使用第三方库,其中比较典型的是 crossbeam 库的 scope() 方法。使用该方法可以让你传递一个引用到新线程。它会阻塞主线程,直到新线程全部完成,因此传递引用是安全的。

或者你可以直接使用 std::mem::transmute()url 的生命周期改成 'static。但是,使用该方式必须小心,你必须手动保证新线程在主线程之前结束。

aariety 2021-07-13 14:29

你是不是后面把 url 传到其他线程去了?能在线程间安全传递的引用只能是 'static 引用,因为新线程的存活时间可能比主线程长;而这个 url 的生命周期与 conf 是相同的,即与主线程一样长,传到其他线程是不安全的。

就此问题而言,我认为最好的解决办法是用 to_string 复制一下字符串再使用。

也有其他的解决方法,比如使用第三方库,其中比较典型的是 crossbeam 库的 scope() 方法。使用该方法可以让你传递一个引用到新线程。它会阻塞主线程,直到新线程全部完成,因此传递引用是安全的。

或者你可以直接使用 std::mem::transmute()url 的生命周期改成 'static。但是,使用该方式必须小心,你必须手动保证新线程在主线程之前结束。

作者 sunnyregion 2021-07-12 08:01

Ok(())这个是有的,我贴例子没有贴全

--
👇
johnmave126: 这main函数不完整吧,连返回都没有的,你后面怎么使用的url和sec啊,可能跟那些有关。

johnmave126 2021-07-10 05:51

main函数不完整吧,连返回都没有的,你后面怎么使用的url和sec啊,可能跟那些有关。

作者 sunnyregion 2021-07-09 18:07

目前的解决方案是把这段代码单独提取为函数

/// 读取ini配置
fn get_ini()->IniURL{
    let conf = Ini::load_from_file("conf/appconf.ini").unwrap();
    let sec =conf.section(Some("Vendor")).unwrap();  //:&'a Option<&Properties<'static>>
    let  url=sec.get("url").unwrap();
    let  zip=sec.get("zip").unwrap();
    let result:IniURL=IniURL{url:url.to_string(),zip:zip.to_string()};
    result
}
作者 sunnyregion 2021-07-09 15:58

样子例子的网址 https://github.com/zonyitoo/rust-ini

1 共 9 条评论, 1 页