简体   繁体   English

这个 mem::transmute::<&str, &'static str>(k) 安全吗?

[英]Is this mem::transmute::<&str, &'static str>(k) safe?

I'm looking at this code which is a very simple library with just one file and mostly tests, so it's short.我正在查看这个代码,它是一个非常简单的库,只有一个文件并且主要是测试,所以它很短。 There's a struct that I'm trying to understand:我试图理解一个结构:

pub struct ChallengeFields(HashMap<UniCase<CowStr>, (String, Quote)>);

struct CowStr(Cow<'static, str>);

There's a line where it does有一条线

pub fn get(&self, k: &str) -> Option<&String> {
    self.0
        .get(&UniCase(CowStr(Cow::Borrowed(unsafe {
            mem::transmute::<&str, &'static str>(k)
        }))))
        .map(|&(ref s, _)| s)
}

I'm annoyed by this unsafe operation.我对这种unsafe的操作感到恼火。 I think CowStr is a Cow with 'static lifetime otherwise it'd be hard or impossible to store str s inside the map.我认为CowStr是具有'static生命周期”的Cow ,否则很难或不可能将str存储在 map 内。 Because of that, when I try to get something inside this map, the str in question has to have 'static lifetime.正因为如此,当我试图在这个 map 中获取一些东西时,有问题的str必须具有'static生命周期”。 This is the reason for the transmute , right?这就是transmute的原因吧? If so, why simply not use String , so we can get rid of lifetimes and thus transmute ?如果是这样,为什么干脆不使用String ,这样我们就可以摆脱生命周期,从而transmute I don't like unsafe , and reading about transmute it looks very unsafe.我不喜欢unsafe ,并且阅读有关transmute的内容看起来非常不安全。

Also, I don't see why Cow is needed at all.另外,我根本不明白为什么需要Cow

I think CowStr is a Cow with 'static lifetime otherwise it'd be hard or impossible to store strs inside the map.我认为CowStr是具有'static生命周期”的Cow ,否则很难或不可能将 strs 存储在 map 内。

Well yes and no, you can store &'static str inside a hashmap with no issue, the problem is that you can't store both &'static str and String .好吧,是也不是,您可以毫无问题地将&'static str存储在 hashmap 中,问题是您不能同时存储&'static strString

Am I rigth?我说得对吗? If so, why simply not use String, so we can get rid of lifetimes and thus transmute?如果是这样,为什么干脆不使用字符串,这样我们就可以摆脱生命周期,从而转化?

I assume that is an optimisation: with String you'd have to create an allocation every time you want to insert a challenge in the map, but if the overwhelming majority of challenge names would be Digest and Basic then that's a waste of time (and memory but mostly time), but at the same time you'd have to support String for custom auth schemes.我认为这是一种优化:使用String时,每次您想在 map 中插入挑战时都必须创建分配,但如果绝大多数挑战名称是DigestBasic ,那么这是浪费时间(并且memory 但主要是时间),但同时您必须支持自定义身份验证方案的String

Now maybe in the grand scheme of things this is not an optimisation which actually matter and it'd be better off not doing that, I couldn't tell you.现在,也许从总体上看,这并不是一个真正重要的优化,最好不要这样做,我不能告诉你。

I don't like unsafe, and reading about transmute it looks very unsafe.我不喜欢不安全的,并且阅读有关 transmute 的内容看起来非常不安全。

It's a debatable thing to do, but in this case it's "safe", in the sense that the reference is valid for the entirety of the HashMap::get call and we know that that call doesn't keep the reference alive (it's reliance on an implementation detail which is a bit risky, but the odds that that would change are basically nil as it wouldn't make much sense).这是一件值得商榷的事情,但在这种情况下它是“安全的”,因为引用对整个HashMap::get调用有效,我们知道该调用不会使引用保持活动状态(它是依赖在一个有点冒险的实现细节上,但改变的可能性基本上为零,因为它没有多大意义)。

Extending lifetimes is not in-and-of-itself UB (the mem::transmute documentation literally provides an example doing that), but requires care as you must avoid it causing UBs (the most likely being a dangling reference).延长生命周期本身并不是 UB( mem::transmute文档确实提供了一个这样做的示例),但需要小心,因为您必须避免它导致 UB(最有可能是悬空引用)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM