[rust] durée de vie et scopes

la durée de vie des références passée au microscope électronique ;-)

a marqué ce sujet comme résolu.

Salut, Voici un bout de code:

struct Foo<'a> {
    bar: &'a i32
}

fn main() {
    let i = 100;
    let j = 100;
    let a = create(&i);
    let b = create(&j);
    let r = get_bigger_bar(&a,&b);
    println!("{}",r);
}

fn create(i:&i32) -> Foo {
    Foo{bar:i}
}

fn get_bigger_bar<'a>(a:&'a Foo,b:&'a Foo) -> &'a i32 {
    if a.bar < b.bar {
        a.bar
    } else {
        b.bar
    }
}

je remarque que les variable a et b ont une durée de vie notée 'a. Est-ce parce que ils viennent de "la même profondeur de scope" ?

j’imagine ça comme des poupées russes dans la stack (ça se passe bien dans la stack ??). Peux t on avoir des scopes de même profondeur par rapport au main, mais néanmoins dans des scopes "parallèles" (donc pas les même scopes, je pense aux threads ou au multicore ou au multiplexage).

comment passer le binaire au microscope en passant par du desassemblage pour visualiser les scopes ? (comment voit on en assembleur que deux variables sont dans un même scope ?)

à quoi correspond cette durée de vie: 'static ? deux variables de durée de vie 'static sont donc dans un même et unique scope ? est-ce le heap ? la section .bss en asm ?

quel lien entre une durée de vie et l’adresse mémoire ?

+0 -0

Salut,

Qu’est-ce que tu entends par « profondeur de scope » ?

La notation 'a dans les paramètres de la fonction ne veut pas dire que les deux variables reçues ont la même durée de vue, mais que 'a correspond à la plus courte des deux.
Ça sert à préciser que la durée de vie des paramètres doit être au moins aussi grande que celle de la valeur de retour.

Tout ça c’est quelque chose de connu à la compilation, mais ça disparaît dans l’exécutable généré où il est seulement question d’accéder à des emplacements mémoires (mais que l’on sait valides).

Quant à 'static, elle correspond à la durée de vie du programme, ce sont les valeurs contenues dans la mémoire statique du programme.

@entwanne : par profondeur de scope, pour imager ce que j’entend par là, un snippet trouvé ici https://dev.to/takaakifuruse/rust-lifetimes-a-high-wall-for-rust-newbies-3ap

fn main() {
    'a: {
        let x: i32 = 0;
        'b: {
            let y: &'b i32 = &'b x;
            'c: {
                // ditto on 'c
                let z: &'c &'b i32 = &'c y;
            }
        }
    }
}

ou encore:

>>> def outer():
...     x = 0
...     def inner():
...         y = 0
...         def inception():
...             nonlocal y
...             y = 10
...         inception()
...         nonlocal x
...         x = y
...     inner()
...     return x
+0 -0

Salut,

Les lifetimes en Rust ne sont pas un concept lié à la stack, ou à un quelconque concept qui existe à l’exécution. Et en fait, ils ne sont pas liés non plus directement à la profondeur d’accolades (si on inclut les blocs { } non-nommés dans cette notion) : les lifetimes étaient étroitement liés à ce type de scope dans les anciennes versions de Rust, ils ne le sont plus vraiment dans les nouvelles (avant, il suffisait de faire des déclarations à l’intérieur d’un bloc non-nommé pour que le compilateur laisse plus ou moins tranquille ce que tu déclares à l’intérieur, maintenant il va plus loin que ça).

Plus généralement, les lifetimes n’existent qu’à la compilation et sont une indication pour le compilateur.

Les lifetimes sont un concept abstrait qui te permet d’effectuer une désambiguïsation à propos de la portée d’un argument de fonction, d’une valeur de retour ou d’un élément de structure. Ils te permettent d’indiquer qu’un identifiant (de variable, d’élément de structure, etc.) vivra au moins aussi longtemps qu’un autre. Cela est surtout utile dans des cas comme ceux-ci :

  • Pour s’assurer qu’une valeur de retour, si elle fait référence à par exemple un argument, vit au moins longtemps que cet argument (dans ce cas, les arguments concernés et la valeur de retour devront partager les mêmes lifetimes),
  • Pour s’assurer qu’un élément de structure, s’il contient une référence à autre chose, vivra au moins aussi longtemps qu’un autre élément de structure dont il dépend, ou que la structure elle-même, ou qu’un lifetime passé comme générique à la structure, etc.

En effet, dans ces cas-là, le lifetime constituera une aide obligatoire pour que le compilateur comprenne ce que tu veux faire sans trop se prendre la tête et effectue les bonnes vérifications. Il faut comprendre les vérifications de Rust seront suffisamment strictes dans tous les cas pour que ton code soit memory-safe (sauf si tu utilises un mot-clef comme unsafe ou que tu imbriques du C), simplement, parfois, il faut aiguiller le compilateur pour qu’il comprenne que tu as une raison légitime de faire sortir de ta fonction/structure une référence à une variable qui a été définie à un niveau supérieur, afin qu’il ne soit pas « trop » strict.

Dans les premières versions de Rust, il fallait vraiment spécifier des lifetimes de partout dans les programmes et les fonctions, bien plus que dans les cas que j’ai mentionné ci-dessus, et c’était vraiment peu lisible. Ça s’est amélioré depuis (grâce à la fonctionnalité nommée « lifetime elision », qui désigne le fait de devoir n’en spécifier que dans certains cas, tout simplement).

Concernant le mot-clef 'static, il désigne plus ou moins ce qui se ramène au mot-clef static en C, c’est-à-dire des données constantes, en principe en lecture seule et définies à la compilation (cela va correspondre au segment .data ou .rodata au niveau ELF).

Bonne journée,

+5 -0

Salut,

Concernant le mot-clef 'static, il désigne plus ou moins ce qui se ramène au mot-clef static en C, c’est-à-dire des données constantes, en principe en lecture seule et définies à la compilation (cela va correspondre au segment .data ou .rodata au niveau ELF).

r0anne

Juste sur ce point, en C, les données de classe de stockage statique ne sont pas constantes (sauf si l’on utilise le qualificateur const).

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte