Me deparei com o seguinte cenário:
fn compute_values(value: &mut String) {
// the first computation should always work:
let computed_value = String::from("computed value");
// override the default String with the computed value:
*value = computed_value;
// some more code that returns a Result with values or an error message
}
fn main() {
let mut value = String::from("default value");
compute_values(&mut value);
println!("value: {value}")
}
Este código é compilado com my rustc 1.74.1 (a28077b28 2023-12-04)
e gera value: computed value
como eu esperava, mas a questão é: se esse código vazar memória.
Pelo que entendi, ele *value = computed_value;
entra e não está mais disponível (o compilador Rust confirma isso, não posso depois) e não é desalocado quando o escopo da função termina. Como esta linha está efetivamente atribuindo a a a , suponho que todos os campos da estrutura sejam copiados para o local da estrutura original. Mas uma vez que a referência contida original é substituída, não há como desalocar a memória heap original que o antigo apontava. Como não estou usando nenhum Rust inseguro e o Rust parece ser seguro para a memória, só posso imaginar que a memória original seja desalocada automaticamente antes que a atribuição aconteça, mas não consegui encontrar nenhuma informação sobre esse tópico.computed_value
*value
println!("{computed_value}");
struct String
struct String
&str
&str
Encontrei os seguintes artigos que não responderam à minha pergunta:
- Existe uma maneira de atualizar uma string enferrujada?
- Como posso trocar um novo valor por um campo em uma referência mutável a uma estrutura?
- Como posso substituir todos os campos em uma referência mutável usando outra estrutura?
As respostas nomeadas std::mem::take
e std::mem::swap
que std::mem::replace
me levam a crer que o uso de uma delas é necessário neste caso.
Também verifiquei a documentação oficial sobre ferrugem, mas não encontrei nada.
Minhas perguntas são:
- Este código está vazando memória?
- O Rust não inseguro deveria ser seguro para a memória, mesmo ao substituir valores de referências mutáveis?
- Existe alguma documentação (oficial) sobre a atribuição de desreferência?
PS: Teoricamente, o Rust pode otimizar let mut value = String::from("default value");
de forma que String
value
aponte para a constante da string e não para um local no heap. Isso não tornaria necessário desalocar a memória. Mas a coisa toda também funciona quando você lê a value
from stdin e a coisa toda deve ser necessariamente colocada na pilha.
Responder
Depois de ler a resposta de @cyqsimon (que é ótima, aliás), entendi que essa pergunta realmente não tem nada a ver com referências e, em vez disso, trata de descartar valores quando eles são substituídos. Armado com esse novo insight, encontrei este artigo do Rustonomicon que responde totalmente à minha pergunta e também fala sobre o que acontece quando as variáveis são apenas inicializadas e, portanto, descartadas sob certas condições.