creates temporary which is freed while still in use when reading path of DirEntry

I’m trying to read all files in a folder, as simple as that. And then filter for mp4 extensions. But I get following error:

create a temporary which is freed error

I don’t understand, how in the following code, the e.path statement could "create a temporary". (The whole code is obviously in them same "Ok" closure.). Is there some special stuff happening in the path() method? I could not find anything strange in the documentation.

let paths = fs::read_dir(&folder).unwrap();

for path in paths {
    match path {
        Ok(e) => {
            let fullPath = e.path();
            let extension = e
                .path()
                .extension()
                .expect("Error getting extension")
                .to_str()
                .expect("Could not convert extensions to string");
            println!("{}", extension)
        }

        _ => {}
    }

I tried numerous things and stuff like .path().metadata() does not throw this error. Only when in combination with extension() this seems to be happening? It’s really confusing me, how a task this simple becomes so complex.

>Solution :

DirEntry::path() returns a PathBuf, and PathBuf::extension() returns an Option<&OsStr>. As you can see, the OsStr is borrowed from the original PathBuf / Path. The problem is, you’re trying to bind the extension to a variable, but you do not assign the PathBuf that is borrowed from to a variable as well.

So the compiler is correct in saying that the PathBuf is temporary, and will be dropped after your let extension = ... statement, and thus extension can not keep pointing to it.

You’re already doing the right thing – assigning another copy of that PathBuf to fullPath. So you can just borrow the extension from it.

Here’s a fully self-contained solution:

use std::fs;

fn main() {
    let folder = "./src";
    let paths = fs::read_dir(&folder).unwrap();

    for path in paths {
        if let Ok(e) = path {
            let full_path = e.path(); // This will live at least as long as `extension`, so
                                      // borrowing from it is fine.
            let extension = full_path
                .extension()
                .expect("Error getting extension")
                .to_str()
                .expect("Could not convert extensions to string");
            println!("{}", extension)
        }
    }
}

Leave a Reply