2

ユーザーからの入力を読み取り、それを POP3 ライブラリの URL として使用しようとしています。取得した を文字列スライスに変換するStringと、使用するのに十分な長さではありません。これは、次の 2 つの理由から私にとって奇妙です。

  1. POP3 オブジェクトを使用するものはすべて同じブロック内にあるため、str スライスの有効期間はブロック全体の有効期間である必要があり、すべてをカバーします。

  2. 考えられるほぼすべての異なるコード構成を試しましたが、毎回同じエラーが発生します。

extern crate pop3;
extern crate smtp;
extern crate openssl;
extern crate libc;

use openssl::ssl::{SslContext, SslMethod};
use pop3::POP3Stream;
use pop3::POP3Result::{POP3Stat, POP3List, POP3Message};

mod readline;
use readline::*;

fn main() {
    let place = match readline("URL: ") {             // Problem line
        Some(input) => {                              // Problem line
            let place: &'static str = &input[..];     // Problem line
            let mut email_socket = match POP3Stream::connect(place, 995, Some(SslContext::new(SslMethod::Sslv23).unwrap())) { // Problem line
                Ok(s) => s,
                Err(e) => panic!("{}", e)
            };

            match readline("Username: ") {
                Some(username) => {
                    match readline("Password: ") {
                        Some(password) => { email_socket.login(&*username, &*password); },
                        None           => println!("Please enter a password.")
                    }
                },
                None           => println!("Please enter a username.")
            };

            let stat = email_socket.stat();
            match stat {
                POP3Stat {num_email,
                          mailbox_size} => println!("num_email: {},  mailbox_size:{}", num_email, mailbox_size),
                e => println!("There was an error signing into your server."),
            }

            let list_all = email_socket.list(None);
            match list_all {
                POP3List {emails_metadata} => {
                    for i in emails_metadata.iter() {
                        println!("message_id: {},  message_size: {}", i.message_id, i.message_size);
                    }
                },
                _ => println!("There was an error listing your messages."),
            }

            let message_25 = email_socket.retr(25);
            match message_25 {
                POP3Message{raw} => {
                    for i in raw.iter() {
                        println!("{}", i);
                    }
                },
                _ => println!("There was an error getting your 25th message."),
            }

            email_socket.quit();
        },
        None        => { println!("Please enter a URL for your server."); }
    };
}
4

1 に答える 1

2

問題

staticキーワードは基本的に「このオブジェクトを永遠に保持する」と言っているので、問題はの使用に要約されます。これは、 の寿命がplace間違いなく長く続くことを意味します —ブロックのスコープに対して永遠inputに。

fn get() -> Option<String> {
    Some("hello world".to_owned())
}
fn main() {
    let data = match get() {
        Some(input) => { let place : &'static str = &input[..]; },
        None        => { }
    };
}

place上記では、 a へのstatic参照を作成しようとしていstrます。つまり、; プログラムの全期間にわたって存在する参照。input一方、この時間の間は存在しないことは間違いないため、エラー診断が表示されます。

<anon>:7:54: 7:59 error: `input` does not live long enough
<anon>:7         Some(input) => { let place : &'static str = &input[..]; },

ソリューション

の使用を削除し、 の寿命はブロックstaticの寿命であると効果的に言いplaceます (これは に関連付けられた寿命のサブセットですinput)。

fn get() -> Option<String> {
    Some("hello world".to_owned())
}
fn main() {
    let data = match get() {
        Some(input) => { let place : &str = &input[..]; },
        None        => { }
    };   
}


さらに掘り下げる

結局のところ、最初の引数としてPOP3Stream::connecta を受け入れます。&'static str文字列リテラルのみを受け入れるため、これは本当に悪い設計です。

impl Pop3Stream {
    pub fn connect(host: &'static str, ...) -> Result<POP3Stream> {
        ...
    }
}

ただし、意図的にリソースをリークすることで、問題を回避することができます。つまり、リソースを効果的に「永久に」存続させることができます。の使用法に注意してくださいunsafe。これは、言語設計により、それだけであると見なされることに注意してください。

fn get () -> Option<String> {
  Some("hello world".to_owned ())
}
fn connect (host : &'static str) {
  /* ... */
}
fn main() { 
    let data = match get() {
        Some(input) => {
            let place : &'static str = unsafe {
                use std::mem; let x = mem::transmute(&input as &str);
                mem::forget (x);  x
            };  

            connect(place);
        },
        None => { }
    };   
}
于 2015-10-08T14:52:01.720 に答える