IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Preuve de programme en C


Sujet :

C

  1. #1
    Futur Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2012
    Messages : 18
    Points : 8
    Points
    8
    Par défaut Preuve de programme en C
    Salut à tous,
    je viens en demande d'aide ^^

    J'ai un souçi pour la preuve du programme suivant avec frama-c et jessie.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    int min2_array(int * a, int n) {
    
      int imin1 = 0; 
      int imin2 = -1;
    
      /*@
        loop invariant (i <= n) && 
    (\forall integer k; 
       (1 <= k < i) ==>
            ((a[k] >= a[imin1])
         && ((imin2 == -1) || (a[k] == a[imin1]) || (a[k] >= a[imin2]))
         && ((imin2 == -1) || (a[imin2] >= a[imin1])) ));
        loop variant n-i-1;
      */
    
      int i;
      for(i = 1; i < n; i++) 
      {
        if (a[i] < a[imin1]) 
        {
          imin2 = imin1;
          imin1 = i;
        }
        else if ((a[imin1] < a[i]) && ((imin2 == -1) || (a[i] < a[imin2])))
          imin2 = i;
      }
    
      return imin2;
    }
    La spécification est simple : le programme renvoie la position du second minimum du tableau (par valeurs strictes entre le premier et le second).
    Il renvoie "-1" si le minimum strict du tableau est à la première case (indice 0 donc).

    Néanmoins: d'une part, l'invariant de boucle que j'ai mis fait des erreurs, et d'autre part je n'arrive pas à trouver de préconditions...

    Donc voilà, j'espère que vous pourrez m'aider.

    Merci à tous!

  2. #2
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Points : 28 129
    Points
    28 129
    Par défaut
    Bonjour,

    Je ne connais pas frama-c ni jessie, or je pense que ton probleme est plus lie a ca qu'au langage C.

    Neanmoins, quelques remarques :
    En C, les indices de tableau commencent a 0, pas a un, d'ou un soucis dans ta boucle for.
    Tu ne verifies pas que a n'est pas NULL. Or c'est la premiere chose a faire.

    Dans le commentaire-specifique, tu as des choses etranges :

    /*@
    loop invariant (i <= n) &&
    (\forall integer k;
    (1 <= k < i) ==>
    ((a[k] >= a[imin1])
    && ((imin2 == -1) || (a[k] == a[imin1]) || (a[k] >= a[imin2]))
    && ((imin2 == -1) || (a[imin2] >= a[imin1])) ));
    loop variant n-i-1;
    */
    Tu dis que i doit etre inferieur ou egal a n. OK
    Tu dis que k doit etre compris entre 1 et i-1 (k<i). Donc pour tout k compris entre 1 et n-1. Si c'est bien ce que tu veux, c'est mal ecrit : pour gagner en lisibilite, tu devrais essayer de toujours avoir des inferieurs strict ou des inferieur ou egal, mais pas les deux
    Ensuite, tu enonces des conditions : A && B && C
    A : rien de special
    B : composee de X || Y || Z : si ton verificateur ne fait pas d'evaluation paresseuse, c'est a dire qu'il ne s'arrete pas des que la premiere condition est verifiee, alors tu as un soucis dans le cas ou imin2 vaut -1 :
    imin2 == -1 : VRAI
    a[k] == a[imin1] : on s'en fout
    a[k] >= a[imin2] : tu accedes a a[-1], ce qui est clairement une erreur.
    D'ailleurs, si imin2 vaut 0, tu as aussi un probleme : tu manipules a pour des indices allant de 1 a N-1 (ce qui est probablement une erreur vu que les tableaux en C vont de 0 a N-1), et tu as une condition sur a[0]

    Bref, pas mal de legers problemes, mais a confirmer car je ne connais pas frama-c ou jessie.

  3. #3
    Futur Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2012
    Messages : 18
    Points : 8
    Points
    8
    Par défaut
    Salut, merci de ta réponse.

    Par rapport à ta première remarque concernant le code, en fait le code est donné et on ne doit pas le modifier, nous ce qu'on doit faire c'est mettre en commentaire les annotations ACSL uniquement. Et la boucle for commence à 1 parce que imin1 est déjà initialisé à 0 (en fait on force le premier tour de boucle en disant que le minimum du tableau c'est la première case au premier tour).

    Après pour l'évaulation paresseuse, c'est pour ça que j'ai mis le imin2 == -1 en premier mais ça ne change rien au final donc bon ...

  4. #4
    Futur Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2012
    Messages : 18
    Points : 8
    Points
    8
    Par défaut
    Peut-être que ce sujet aurait sa place dans une autre section ?

  5. #5
    Expert confirmé Avatar de ManusDei
    Homme Profil pro
    vilain troll de l'UE
    Inscrit en
    Février 2010
    Messages
    1 619
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : vilain troll de l'UE

    Informations forums :
    Inscription : Février 2010
    Messages : 1 619
    Points : 4 352
    Points
    4 352
    Par défaut
    Il n'y a pas vraiment de forum pour la preuve de programme (enfin pas que je sache).

    Comme précondition, n > 2 ?
    Tu peux aussi vérifier en précondition que a est différent de NULL, comme le propose gangsoleil (donc sans modifier le code).

    A ce que je pense en comprendre, l'erreur est peut-être plutôt dans la syntaxe.
    Tu as essayé de noter ton invariant sur papier pour voir ? Tu peux séparer ton invariant en plusieurs cas, pour détecter plus facilement d'où vient le problème ?

    Si non, met juste
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    \forall integer k; 
     (1 <= k < i) ==>
     (a[k] >= a[imin1])
    en invariant, si ça plante pas rajoute le bout suivant, etc....

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2011
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2011
    Messages : 25
    Points : 68
    Points
    68
    Par défaut
    Salut,

    Citation Envoyé par gangsoleil Voir le message
    Tu ne verifies pas que a n'est pas NULL. Or c'est la premiere chose a faire.
    Sans vouloir dire, cela me semble plutôt inutile. Recevoir un pointeur nul n'est qu'un cas parmis une multitude de valeurs invalides possible. Je pourrais tout aussi bien provoquer une erreur avec l'appel suivant : min2_array((int *)1, 10). C'est à l'utilisateur de la fonction de faire attention à la validité des valeurs qu'il envoie à cette dernière, pas l'inverse.

  7. #7
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Points : 28 129
    Points
    28 129
    Par défaut
    Citation Envoyé par Taurre Voir le message
    Sans vouloir dire, cela me semble plutôt inutile [de tester un pointeur a NULL]. Recevoir un pointeur nul n'est qu'un cas parmis une multitude de valeurs invalides possible. Je pourrais tout aussi bien provoquer une erreur avec l'appel suivant : min2_array((int *)1, 10). C'est à l'utilisateur de la fonction de faire attention à la validité des valeurs qu'il envoie à cette dernière, pas l'inverse.
    Tu peux faire confiance a l'utilisateur. Mais tu verras vite que la programmation defensive passe avant tout par la protection des valeurs que tu peux tester : Oui, NULL n'est qu'une valeur invalide parmi tant d'autres. Mais c'est celle que tu peux tester, alors pourquoi ne pas en profiter ?

    Acceder a a[i], si a est NULL, va planter.Et comme le code est le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int min2_array(int * a, int n) {
     
      int imin1 = 0; 
      int imin2 = -1;
     
      int i;
      for(i = 1; i < n; i++) 
      {
        if (a[i] < a[imin1]) 
    ...
    le simpe fait de tester a a NULL te permet d'eviter l'erreur.

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2011
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2011
    Messages : 25
    Points : 68
    Points
    68
    Par défaut
    Citation Envoyé par gangsoleil Voir le message
    Oui, NULL n'est qu'une valeur invalide parmi tant d'autres. Mais c'est celle que tu peux tester, alors pourquoi ne pas en profiter ?
    Parce que, à mon sens, cela n'a pas beaucoup d'intérêt. À supposer que l'utilisateur manipule un pointeur nul, il finira tôt ou tard par effectuer une indirection et à provoquer l'arrêt du programme. Alors oui, cela aura lieu dans une autre fonction, mais cela se produira tout de même.

    Au final, le test ne servira qu'avant une interruption et constituera donc plus une perte de temps qu'autre chose. Maintenant, chacun son opinion, mais personnellement je trouve la vérification superflue.

  9. #9
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Points : 28 129
    Points
    28 129
    Par défaut
    Citation Envoyé par Taurre Voir le message
    À supposer que l'utilisateur manipule un pointeur nul, il finira tôt ou tard par effectuer une indirection et à provoquer l'arrêt du programme.
    Sans verification, le programme plante lamentablement.
    Avec verification, la fonction produit une erreur, et le programme ne plante pas.

    Je prefere clairement la seconde.

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2011
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2011
    Messages : 25
    Points : 68
    Points
    68
    Par défaut
    Citation Envoyé par gangsoleil Voir le message
    Sans verification, le programme plante lamentablement.
    Nous sommes bien d'accord sur ce point.
    Nous divergeons juste d'opinion sur qui doit effectuer cette vérification. Pour moi, cette dernière incombe à l'utilisateur de la fonction et non à la fonction elle-même.

  11. #11
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Points : 28 129
    Points
    28 129
    Par défaut
    Citation Envoyé par Taurre Voir le message
    Nous sommes bien d'accord sur ce point.
    Nous divergeons juste d'opinion sur qui doit effectuer cette vérification. Pour moi, cette dernière incombe à l'utilisateur de la fonction et non à la fonction elle-même.
    L'habitude de la programmation defensive : je teste tout, partout, tout le temps.

    La meilleure defense, c'est l'attaque.

Discussions similaires

  1. Algorithme polynomial et preuve de programme
    Par yaya125 dans le forum Algorithmes et structures de données
    Réponses: 1
    Dernier message: 28/02/2011, 18h12
  2. [Fondements] Preuve de programme: utopie ou réalité ?
    Par DrTopos dans le forum Débats sur le développement - Le Best Of
    Réponses: 115
    Dernier message: 05/10/2007, 16h12
  3. Programme de boot qui passe la main à Windows
    Par Bob dans le forum Assembleur
    Réponses: 7
    Dernier message: 25/11/2002, 03h08
  4. [Kylix] Probleme d'execution de programmes...
    Par yopziggy dans le forum EDI
    Réponses: 19
    Dernier message: 03/05/2002, 14h50
  5. [Kylix] icone associée à un programme
    Par Anonymous dans le forum EDI
    Réponses: 1
    Dernier message: 22/03/2002, 09h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo