Publicité
+ Répondre à la discussion
Page 3 sur 4 PremièrePremière 1234 DernièreDernière
Affichage des résultats 41 à 60 sur 77
  1. #41

    Inscrit en
    janvier 2011
    Messages
    30
    Détails du profil
    Informations forums :
    Inscription : janvier 2011
    Messages : 30
    Points : -4
    Points
    -4

    Par défaut

    Tu ne peux donc pas avoir un type void*, ce qui est quand même une des "features" majeures de C..
    Effectivement, il n'y pas de type void* en Safe C, parce que c'est quasiment impossible à vérifier à l'exécution.

    J'ai dû me creuser les méninges pour trouver un équivalent pratique, et après avoir examiné beaucoup de langages je suis arrivé à la solution suivante :

    - ajout d'un attribut 'byte qui permet de convertir tous les types "paqués" en tableau de byte.

    - conversion implicite de tous les types "paqués" en tableau de byte (donc byte[]) lors du passage de paramètres.

    En clair, ces 2 règles permettent les choses suivantes :

    Code :
    1
    2
    3
    4
    5
    6
    7
     
     float f;
     int   i;
     double l;
     
     f'byte = i'byte;   // copie des 4 bytes du i dans les 4 bytes de f
     l'byte[0:2] = i'byte[0:2]; // recopie des 2 premiers bytes de i vers les 2 premiers bytes de l.
    et

    Code :
    1
    2
    3
    4
     
     // fonctions acceptant n'importe quel type "paqué" pour les I/O bas-niveau.
     int read (int fd, out byte[] buffer);
     int write (int fd, byte[] buffer);
    Pour ne pas mettre en péril la sécurité, il y a une restriction sur ces types 'paqués':
    ils ne peuvent pas contenir de pointeur sécurisé (donc p^).
    Cela n'est pas gênant car il est rare de devoir sauver un pointeur sur disque ..

    On peut donc écrire :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    packed struct PERSON
    {
      string(20) nom;
      int        age;
    }
     
    PERSON person;
     
    // ...
     
    rc = write (fd, person);

  2. #42
    gl
    gl est déconnecté
    Rédacteur/Modérateur

    Homme Profil pro
    Inscrit en
    juin 2002
    Messages
    2 096
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : juin 2002
    Messages : 2 096
    Points : 3 957
    Points
    3 957

    Par défaut

    Citation Envoyé par Marc.Samuro Voir le message
    Une chose qu'il faut préciser aussi : en Safe-C, on utilise beaucoup moins les pointeurs qu'en C.

    Par exemple, pour passer des paramètres, le code C suivant :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
     
    void foo (char        *s,    // in
              char        *t,    // ref
              struct INFO *p)    // out
    {
      s[5] = 'a';
      p->age = 30;
    }
    sera ré-écrit comme ceci en Safe-C :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
     
    void foo (    char[] s,
              ref char[] t,
              out INFO   p)
    {
      s[5] = 'a';   // compilation error : s is read-only
      p.age = 30;
    }
    avec l'avantage que le compilateur va donner une erreur si on écrit dans s puisque c'est un paramètre 'in'.
    Juste deux petites remarques:
    • En C, il est possible dans les paramètres de fonctions d'écrire char s[] à la place de char *s. c'est tout à fait licite.
    • Si tu veux un pointeur en lecture seule, il suffit de le déclarer const. Ainsi tu auras le même message d'erreur en C en déclarant non pas "char *s" mais "char const * s". La principale différence par rapport à ton système en out/ref/in c'est le mode par défaut : un oubli en safe-C rends le paramètre read-only et donc soit le code est bon, soit tu te payes une erreur à la compilation alors qu'en C un oubli se paye par un bug potentiel (le mode "lecture seule par défaut est plus sécurisant de ce point de vu là).


    Sinon une petite question concernant la gestion du passage de la structure INFO dans ton cas de figure, empiles-tu toute la structure lors de l'appel de fonction ou seulement son adresse mémoire ?

  3. #43
    Expert Confirmé Sénior

    Inscrit en
    janvier 2007
    Messages
    10 184
    Détails du profil
    Informations personnelles :
    Âge : 56

    Informations forums :
    Inscription : janvier 2007
    Messages : 10 184
    Points : 12 839
    Points
    12 839

    Par défaut

    Citation Envoyé par Marc.Samuro Voir le message
    Effectivement, il n'y pas de type void* en Safe C, parce que c'est quasiment impossible à vérifier à l'exécution.

    J'ai dû me creuser les méninges pour trouver un équivalent pratique, et après avoir examiné beaucoup de langages je suis arrivé à la solution suivante :

    - ajout d'un attribut 'byte qui permet de convertir tous les types "paqués" en tableau de byte.

    - conversion implicite de tous les types "paqués" en tableau de byte (donc byte[]) lors du passage de paramètres.

    En clair, ces 2 règles permettent les choses suivantes :

    ok, mais quid des utilisations comme "any function" ?

    (exemple, la fonction de comparaion de qsort, ou les callbacks)..

    ça ne peut pas être traité comme "un tableau de byte", si ?
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  4. #44

    Inscrit en
    janvier 2011
    Messages
    30
    Détails du profil
    Informations forums :
    Inscription : janvier 2011
    Messages : 30
    Points : -4
    Points
    -4

    Par défaut

    Sinon une petite question concernant la gestion du passage de la structure INFO dans ton cas de figure, empiles-tu toute la structure lors de l'appel de fonction ou seulement son adresse mémoire ?
    Les structs et les tableaux sont passés par adresse je vous rassure, on ne recopie jamais les structures comme en Pascal, ce serait terriblement inefficace.

    ok, mais quid des utilisations comme "any function" ?
    (exemple, la fonction de comparaion de qsort, ou les callbacks)..
    ça ne peut pas être traité comme "un tableau de byte", si ?
    Non bien sûr, ça ne peut être traité comme tableau de byte puisqu'on doit pouvoir trier une structure contenant des pointeurs.

    Pour les algorithmes comme les tris j'ai été quasiment obligé d'ajouter les packages génériques au langage, ce qui permet de paramétriser un type quelconque pour un algorithme donné (= inspiré des packages génériques Ada, des templates C++, des génériques C#, mais en simplifiant très fort et en séparant bien interface et corps de package). Chaque instantiation générique génère alors du code spécialisé pour le type donné, ce qui est comme j'ai pu le constater par des essais pratiques, très efficace. (j'oserais presque dire plus efficace qu'en C parce que la routine qsort ne doit pas appeler la fonction de comparaison par un appel indirect mais peut utiliser un appel direct, les appels indirects comme vous le savez sans doute étant très mal supportés par le Pentium puisqu'ils vident la queue des instructions, provoquant des pénalités importantes - oui j'ai beaucoup lu les manuels d'Intel c'est très instructif pour optimiser et choisir les instructions rapides, tenir compte des tailles de cache, etc ..)

    Un autre besoin pour void* se fait sentir quand on écrit un compilateur : en effet quand on crée une représentation syntaxique des instructions par un gigantesque arbre chainé avec des pointeurs dans tous les sens, on doit représenter des structures pointant vers une multitude d'autres structures.

    Presque tous les langages que je connais ont résolu ce problème en utilisant le concept de 'classe', ainsi que 'classe dérivée'. Cependant je ne voulais pas de ce concept en Safe-C vu la complexité abstraite qu'il génère pour la compréhension des programmes et les pénalités à l'exécution, surtout en cas de conversion d'un type dérivé vers un autre.
    Une fois qu'on introduit les classes dans un langage ce sont les casse-têtes assurés pour la suite : constructeurs, destructeurs, classe abstraite, etc .. et une multitude d'autres concepts qu'on est pratiquement obligé d'ajouter (voir problèmes rencontrés par les designers du C#).

    Donc j'ai choisi une autre voie, plus simple : les struct avec discriminant donc j'ai déjà parlé, je remets ici un exemple :

    Code :
    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
    31
    32
    33
    34
     
     
      enum FIG {RECT, CERCLE};
     
      struct S (FIG f)
      {
        int x, y;
        switch (f)
        {
          case RECT:
            int long, larg;
          case CERCLE:
            int rayon;
        }
      }
     
      S(RECT) s = {x=>1, y=>2, long=>10, larg=>5};
     
      dessine (s);
     
      ....
     
      void dessine (S s)
      {
        switch (s.f)
        {
          case RECT:
            // dessiner un rectangle
            break;
          case CERCLE:
            // dessiner un cercle
            break;
        }
      }
    Dans l'exemple ci-dessus, la fonction dessine() peut recevoir n'importe quelle variante de la struct S et elle peut interroger s.f à l'intérieur de la fonction pour voir quelle forme a été passée en paramètre. C'est implémenté très simplement : dessine() reçoit l'adresse du paramètre s ainsi que son discriminant s.f qui ne fait pas partie de la structure. C'est très similaire aux tableaux où on passe l'adresse et la longueur.

    Le discriminant peut être dynamique aussi si l'objet est réservé sur le heap :

    Code :
    1
    2
    3
    4
    5
     
     
      S^ p = new S(RECT)'{x=>1, y=>2, long=>10, larg=>5};
     
      dessine (p^);
    Pour ceux qui connaissent Ada, la syntaxe en est très proche, sauf qu'en Ada le discriminant fait partie de la structure, ce qui à mon avis est une erreur car elle peut être corrompue par exemple si on passe la structure à une routine d'entrée-sortie. En Safe-C le discriminant ne peut pas changer après création de l'objet : il est soit constant soit read-only et non-accessible car stocké en dehors de l'objet (un peu comme une longueur de tableau qui n'est pas stockée dans le tableau non plus).


    Les callbacks sont traités comme en C, on peut créer des pointeurs vers fonctions, les paramètres doivent être compatibles :

    Code :
    1
    2
    3
    4
    5
    6
     
    typedef void FUNC (int fd);
     
    FUNC f = ...;   // initialiser avec une vraie fonction compatible avec FUNC
     
    f (2);  // appel indirect de la fonction via pointeur f

    p.s: la syntaxe est volontairement brute ici, on peut écrire aussi :

    Code :
    1
    2
    3
    4
    5
     
     
      typedef  S(RECT) UN_RECT;
     
      S^ p = new UN_RECT ' {x=>1, y=>2, long=>10, larg=>5};

  5. #45

    Inscrit en
    janvier 2011
    Messages
    30
    Détails du profil
    Informations forums :
    Inscription : janvier 2011
    Messages : 30
    Points : -4
    Points
    -4

    Par défaut

    j'ai dis plus haut qu'il n'y a pas de classes en Safe-C, en fait il y en a quand même mais des classes ultra-simplifiées : les types opaques.

    Ce sont des types qu'on déclare par :

    dans p.h :

    Code :
    1
    2
    3
    4
    5
    6
     
      // p.h
     
      struct MON_TYPE;
     
      void foo (MON_TYPE t);
    et dans p.c :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
      // p.c
      struct MON_TYPE
      {
         string(80) nom;
         int        age;
      }
     
      void foo (MON_TYPE  t)
      {
         // ...
      }

    L'utilisateur de P peut écrire ceci :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
      // prog.c
     
      use p;
     
      MON_TYPE m;
     
      clear m;
     
      foo (m);
    Un type opaque est sévèrement restreint dans prog.c : on ne peut ni le copier par assignation, ni accéder à ses champs internes, ni le convertir en tableau de byte, etc ... On peut uniquement l'initialiser à zéro avec la commande 'clear' ou le passer à des fonctions. Bref, on ne peut pas corrompre son contenu, on ne peut pas non plus en prendre une copie (donc il peut contenir des pointeurs sans risque qu'ils soient dupliqués). En fait le concept vient des types 'limited private' d'Ada. Ce sont des classes super-simplifiées réduites au minimum et surtout rapides.

    Il n'y a pas de constructeur pour un type opaque (car les constructeurs imbriqués c'est une chose horrible qui ralentit beaucoup les programmes), on peut uniquement initialiser l'objet, soit à zéro avec la commande clear, soit en le passant à une fonction avec paramètre 'out'.

  6. #46
    Membre Expert
    Inscrit en
    avril 2008
    Messages
    998
    Détails du profil
    Informations forums :
    Inscription : avril 2008
    Messages : 998
    Points : 2 192
    Points
    2 192

    Par défaut

    Bonjour,

    d'abord, je suis impressionné par le travail que tu as fait! J'espère juste pour toi que ce n'est pas en vain. Au pire, si personne n'est intéressé, tu pourras toujours l'utiliser pour ton propre travail de développement!

    Citation Envoyé par Marc.Samuro Voir le message
    il m'est déjà arrivé de passer plusieurs jours dans le debugger en train de chercher comment diable une variable pouvait avoir reçu une valeur que normalement elle ne devrait pas, et finalement sans trouver la réponse.
    Personnellement, je trouve plus simple, dans le cas où le bug est reproductible, d'utiliser des outils existants de vérification de la gestion de la mémoire, comme Valgrind, Insure ou Purify.

    Je trouve d'ailleurs que ce serait une bonne chose que tout programme soit suffisamment testé (et "purifié") avec ces outils avant d'être distribué!

    )jack(

  7. #47
    Membre chevronné
    Inscrit en
    mars 2010
    Messages
    308
    Détails du profil
    Informations forums :
    Inscription : mars 2010
    Messages : 308
    Points : 793
    Points
    793

    Par défaut

    Citation Envoyé par Marc.Samuro Voir le message
    Cyclone est resté plus proche du C que Safe-C, apparemment l'un de ses objectifs est de garder exactement les mêmes pointeurs que le C pour améliorer la portabilité, mais en les classant en différentes catégories en plaçant un @ devant
    Je ne pense pas que l'objectif premier soit la "portabilité" mais plus la "compatibilité philosophique". En gros, la question est 'comment rendre sûr du code C, tout en restant le plus proche de l'idée de "je controle tout ce que fait ma machine"'.
    Citation Envoyé par Marc.Samuro Voir le message
    En Safe-C j'ai pris l'approche de garder les anciens pointeurs C (avec *) inchangés mais utilisables uniquement dans une région #begin unsafe .. #end unsafe, et d'introduire un nouveau type de pointeur sûr (avec ^ et le mot-clé 'new'). Cela me semble plus 'propre' que l'approche Cyclone, mais aussi moins compatible avec du C en effet.
    Tes pointeurs safe-c ne sont rien de plus que les fat pointeurs de cyclone, c'est à dire des pointeurs transportant les limites du block mémoire dans lequel ils ont été alloués.
    Ensuite cyclone a fait le choix de ne pas offrir la possibilité d'être unsafe. Ca évite d'avoir un peu trop vite la tentation de commencer tous ses fichiers par #pragma unsafe, et en plus ça a poussé les designers du langage à trouver le plus possible de solution pour les situations les plus courantes en C.

    Bien sûr, il est impossible d'avoir la même flexibilité que quand on a zéro limite comme en C, mais ils sont arrivé à un compromis pas dégueu me semble-t-il.
    Une des limitations principale à mon sens (parce qu'elle ne se limite pas à des différences de performance) est la gestion de la mémoire. Je pense que pour un grand nombre d'applications, les allocations/désallocations étant bien parenthesé, l'approche par région est fondamentalement la bonne (et avec un bon allocateur, peut même donner des meilleurs performances que malloc/free utilisé "naïvement".) Beaucoup d'application ne respectant pas ce "bon parenthesage" resteront sans doute dans le domaine d'application du pointeur unique (je n'ai pas encore lu cette partie du manuel, mais je pense que c'est juste un pointeur sans alias, que l'on peut donc libérer sans contrainte)
    En revanche, dès qu'il faut allouer dans le tas principal (la région `H), il faut se reposer sur un GC conservatif, et là il y a inévitablement risque de fuite de mémoire (en plus évidement de l'aspect performance).


    Citation Envoyé par Marc.Samuro Voir le message
    en Safe-C, à moins d'utiliser une région #begin unsafe .. #end unsafe, il vous sera impossible de corrompre la mémoire, donc en clair : impossible de lire ou d'écrire en mémoire en dehors d'une variable.
    Est ce qu'à ce sujet, tu pourrais décrire un peu plus précisément comment tu gères free ? En gros plutôt que nous dire "c'est safe", explique nous un peu plus précisément pourquoi Parce qu'avoir un pointeur qui trimbale ses bornes, c'est pas trop difficile. Gérer la mémoire désalloué, c'est moins simple. Je serais donc intéressé de voir comment tu fais ça

    Un autre choix de Cyclone est aussi d'ajouter des exceptions à C. Ce qui permet de ne pas juste arrêter le programme avec un message d'erreur en cas de déréférencement d'un pointeur hors borne.


    Citation Envoyé par Marc.Samuro Voir le message
    Personnellement j'aime bien créer les choses pour les maitriser entièrement. J'utilise rarement dans mes programmes du code que je n'ai pas digéré ou retravaillé parce qu'on est horriblement coincé s'ils contiennent des bugs ou des limitations et qu'on ne sait pas y remédier. Et puis ça donne beaucoup de satisfaction et de motivation ...
    C'est sûr que réécrire ses petits outils ou ses petites fonction, c'est une bonne idée. Réécrire un compilo, c'est quand même fortement risquer d'avoir des milliers de bugs pour des perfs bien moindre àmha.

    Sur la partie compilation pure, j'insiste encore, mais quelle genre d'optimisation as tu ? Parce que "lire la doc intel pour trouver la bonne instruction", c'est bien, mais si tu n'as pas de propagation des constantes ou d'élimination des sous expression communes, ou encore d'inliner,c'est sans doute pas bien utile...

    Citation Envoyé par Marc.Samuro Voir le message
    Effectivement, il n'y pas de type void* en Safe C, parce que c'est quasiment impossible à vérifier à l'exécution.
    Citation Envoyé par souviron34 Voir le message
    ok, mais quid des utilisations comme "any function" ?
    La solution naturelle ici est bien sûr le polymorphisme (void*, c'est juste le polymorphisme du pauvre). C'est le choix fait en Cyclone par exemple.

  8. #48

    Inscrit en
    janvier 2011
    Messages
    30
    Détails du profil
    Informations forums :
    Inscription : janvier 2011
    Messages : 30
    Points : -4
    Points
    -4

    Par défaut

    je vais rédiger un texte qui décrit les grandes lignes du Safe-C pour programmeurs expérimentés, en commençant par les concepts et en terminant par les détails. C'est vrai que ce n'est pas évident de cerner un langage sans avoir une base de travail, et le manuel de normalisation que j'ai actuellement est un peu trop indigeste à lire, et il n'explique pas les concepts ..

  9. #49
    Membre chevronné
    Inscrit en
    mars 2010
    Messages
    308
    Détails du profil
    Informations forums :
    Inscription : mars 2010
    Messages : 308
    Points : 793
    Points
    793

    Par défaut

    Citation Envoyé par Marc.Samuro Voir le message
    je vais rédiger un texte qui décrit les grandes lignes du Safe-C pour programmeurs expérimentés
    Bon courage

  10. #50

    Inscrit en
    janvier 2011
    Messages
    30
    Détails du profil
    Informations forums :
    Inscription : janvier 2011
    Messages : 30
    Points : -4
    Points
    -4

    Par défaut

    voilà, ouf terminé !

    Un tutorial Safe-C pour programmeurs expérimentés : ---> http://newchatrooms.dyndns.dk:12000/...AL/manuel.html

    j'aurai dû commencer par cela, cela m'aurait évité pas mal de questions dans tous les sens ..

  11. #51
    Membre chevronné
    Inscrit en
    mars 2010
    Messages
    308
    Détails du profil
    Informations forums :
    Inscription : mars 2010
    Messages : 308
    Points : 793
    Points
    793

    Par défaut

    Citation Envoyé par Marc.Samuro Voir le message
    voilà, ouf terminé !

    Un tutorial Safe-C pour programmeurs expérimentés : ---> http://newchatrooms.dyndns.dk:12000/...AL/manuel.html

    j'aurai dû commencer par cela, cela m'aurait évité pas mal de questions dans tous les sens ..
    Merci d'avoir écrit ça.

    Un premier commentaire: ton blabla initial est passablement inutile et à même de crisper les gens pas tout à fait d'accord avec toi

    Déjà, un langage antique et toujours utilisé aujourd'hui : le lisp. Nettement plus vieux que le C

    Ensuite tu dis "un programme est fiable si quand il crash, ce n'est pas de sa faute". Un programme qui crash n'est *pas* un programme fiable.

    Ensuite, tu dis "langage fiable == langage qui vérifie que les accès sont dans les bornes". Disons que la vérification des bornes est le minimum du minimum vital d'un langage "fiable". La fiabilité d'une application ne se résume pas à "on n'a pas de corruption mémoire". Va essayer d'expliquer à une autorité de certification que ton avion peut voler sans problème par ce que "on est sur qu'il n'y a pas d'accès en dehors des bornes"..

    Ensuite, tu dis que les langages modernes sont tous "10 fois plus gros et complexe que le C". Qu'est ce que tu entends par là ? Parce que si tu compare la norme du C à la norme de SML par exemple (Standard ML, langage fonctionnel de la famille Caml), tu te rendras vite compte que le C est *beaucoup* plus complexe que SML, rien qu'au nombre de page. Pour comprendre le C, tu dois maitriser son modèle mémoire, et rien que ça, ça en fait un langage d'une complexité effroyable.

    Finalement tu dis que "En clair : avec le Safe-C vous avez un langage un tout petit peu plus lent que le C afin de pouvoir satisfaire l'objectif 1 de fiabilité, mais qui reste le plus rapide qu'il soit possible de faire avec cet objectif.". Le fait qu'en restant dans la partie "safe" du safe-C, on soit obligé de se trimbaler des pointeurs "vérifié" montre que cette affirmation est fausse. Je suis près à parier ce que tu veux que Cyclone est plus rapide que ton safe-C sur plein d'application où on peut trivialement éviter les fat pointers

    Puisque ton seul objectif est la sureté, pourquoi forcer l'initialisation des valeurs ? Seuls la non initialisation des pointeurs pose un soucis.

    En C, le chiffre derrière int est le nombre de bit, toi d'octet. C'est confusant.

    Le mécanisme de "Tombstone" me semble assez étonnant. Si je comprends bien, à partir du moment où tu as créé un pointeur, sa "Tombstone" restera là pour toujours. Donc en gros, si je fais

    Code :
    1
    2
    3
    4
    5
     
    while(1){
      int ^p = new int;
      free p;
    }
    je ferai exploser ma mémoire.
    Embêtant non ?
    Est ce que tu as un lock par tombstone pour être thread safe ?

    Je suis vraiment désolé, je continue à penser que c'est un travail impressionnant, mais qu'il n'apporte rien d'intéressant par rapport à des projets existant, tels que Cyclone :-\

  12. #52
    Membre chevronné
    Inscrit en
    mars 2010
    Messages
    308
    Détails du profil
    Informations forums :
    Inscription : mars 2010
    Messages : 308
    Points : 793
    Points
    793

    Par défaut

    Je viens de penser à des problèmes potentiellement encore plus graves avec tes "tombstones". Est ce que tu peux nous faire une description plus poussée de ce que tu fais ? La vraie structure mémoire, et ce qu'il se passe à run time, en particulier l'arithmétique de pointeurs.

    Merci !

  13. #53

    Inscrit en
    janvier 2011
    Messages
    30
    Détails du profil
    Informations forums :
    Inscription : janvier 2011
    Messages : 30
    Points : -4
    Points
    -4

    Par défaut

    ton blabla initial est passablement inutile et à même de crisper les gens pas tout à fait d'accord avec toi
    je suis d'accord, je vais raccourcir l'introduction.

    Déjà, un langage antique et toujours utilisé aujourd'hui : le lisp. Nettement plus vieux que le C
    qui programme encore en Lisp ?

    Ensuite, tu dis que les langages modernes sont tous "10 fois plus gros et complexe que le C".
    je parle de la taille du compilateur qu'il faut pour supporter le langage.

    ---------------------------

    tu parles toujours des fat pointers de Cyclone,
    est-ce que ce sont des structures composées d'un pointeur et d'une taille ?

    Que se passe-t-il si 2 threads accèdent à cette structure en même temps,
    par exemple une assignation d'une valeur pointeur à une variable fat pointer,
    ne risquent-ils pas de la corrompre ?

    En Safe-C je voulais expressément des pointeurs de la taille d'une adresse
    mémoire pour que les assignations de pointeurs soient naturellement thread-safe.

    ----------------------------

    Puisque ton seul objectif est la sureté, pourquoi forcer l'initialisation des valeurs ? Seuls la non initialisation des pointeurs pose un soucis.
    Effectivement c'est une faille dans mon argumentation à laquelle j'ai pensé aussi.
    Le problème c'est que si je renonce à l'initialisation des variables, je ne sais plus introduire les nouveaux modes de passage de paramètres.
    D'autre part, avoir des variables non-initialisées crée des programmes qui ne se comportent pas d'une manière déterministe, ce qui complique fortement la recherche d'erreurs.

    Il faudra peut-être que je nuance ma définition de 'safe' ..

    Je suis près à parier ce que tu veux que Cyclone est plus rapide que ton safe-C sur plein d'application où on peut trivialement éviter les fat pointers
    J'ai vu qu'en cyclone on peut créer un scope pour un pointeur. Pourquoi ne pas utiliser une variable locale à la place ?


    Code :
    1
    2
    3
    4
    5
    6
    7
    8
     
    while(1){
      int ^p = new int;
      free p;
    }
     
    je ferai exploser ma mémoire.
    Embêtant non ?
    télécharge le compilateur et essaye

    Est ce que tu as un lock par tombstone pour être thread safe ?
    Tout est thread-safe grâce au préfixe "lock" d'intel qui permet les opérations atomiques.

    Je viens de penser à des problèmes potentiellement encore plus graves avec tes "tombstones".
    télécharge le compilateur et essaye
    moi je pense à des problèmes graves avec tes fat-pointers.

    :-)

  14. #54
    Membre chevronné
    Inscrit en
    mars 2010
    Messages
    308
    Détails du profil
    Informations forums :
    Inscription : mars 2010
    Messages : 308
    Points : 793
    Points
    793

    Par défaut

    Citation Envoyé par Marc.Samuro Voir le message
    qui programme encore en Lisp ?
    Qui programme encore avec le C de l'époque plutôt qu'en C 90 voir 99 ?

    Citation Envoyé par Marc.Samuro Voir le message
    je parle de la taille du compilateur qu'il faut pour supporter le langage.
    Ca ne me semble pas vraiment être un argument intéressant pour l'utilisateur... "Tu devrais utiliser ce langage. Il est horrible à comprendre, mais c'est plus simple pour les auteurs de compilo". Mais bon, quelque part, c'est ce qui a fait que la C a gagné sur plein de langages bien mieux: il y avait un compilo avec tout nouvel OS et toute nouvelle archi, parce que c'était tout petit à écrire.


    Citation Envoyé par Marc.Samuro Voir le message
    tu parles toujours des fat pointers de Cyclone,
    est-ce que ce sont des structures composées d'un pointeur et d'une taille ?
    Ils sont sur trois mots.


    Citation Envoyé par Marc.Samuro Voir le message
    Que se passe-t-il si 2 threads accèdent à cette structure en même temps,
    par exemple une assignation d'une valeur pointeur à une variable fat pointer,
    ne risquent-ils pas de la corrompre ?
    Je ne sais pas ce que Cyclone promet en multithread.


    Citation Envoyé par Marc.Samuro Voir le message
    J'ai vu qu'en cyclone on peut créer un scope pour un pointeur. Pourquoi ne pas utiliser une variable locale à la place ?
    Je n'ai pas compris la question

    Citation Envoyé par Marc.Samuro Voir le message
    télécharge le compilateur et essaye
    Tout le monde n'a pas windows. C'est pour ça que j'aimerais une description plus fine de tes tombstones. Du peu que tu as dit, je ne vois comment ta structure intermédiaire peu disparaitre, ni comment peut fonctionner l'arithmétique de pointeurs.

    J'ajouterai que mettre un lien vers ton petit projet perso sur wikipedia est assez déplacé. Je suggère fortement que tu le supprimes.

  15. #55

    Inscrit en
    janvier 2011
    Messages
    30
    Détails du profil
    Informations forums :
    Inscription : janvier 2011
    Messages : 30
    Points : -4
    Points
    -4

    Par défaut

    Du peu que tu as dit, je ne vois comment ta structure intermédiaire peu disparaitre, ni comment peut fonctionner l'arithmétique de pointeurs.
    Effectivement j'ai calé sur ce problème de structure intermédiaire pendant 6 mois. Le Wikipédia anglais décrit les tombstones ("pierres tombales" en français) comme des structure de données qui, une fois le block déalloué, ne pouvaient plus êtres allouées à nouveau, d'où consommation de mémoire de plus en plus grande.

    C'est l'auteur d'une note "white paper" qui en parlant de pointeurs m'a donné l'idée qu'en fait on ne risquait pas de corrompre la mémoire si on réutilisait le slot tombstone pour le même "type" d'objet heap. Le tombstone retient donc vers quel type d'objet il pointe.

    En ce qui concerne l'arithmétique de pointeurs, elle n'est tout simplement pas autorisée.

    p.s: j'ai complètement enlevé l'introduction, donc le texte passe directement au coeur du sujet, c'est beaucoup mieux en effet

    J'ajouterai que mettre un lien vers ton petit projet perso sur wikipedia est assez déplacé. Je suggère fortement que tu le supprimes.
    pourquoi donc ? il illustre un langage qui utilise les tombstones. Il n'y a rien de mal à cela sinon les wikipediens l'auraient déjà supprimé depuis le temps qu'il est là.

  16. #56
    Membre chevronné
    Inscrit en
    mars 2010
    Messages
    308
    Détails du profil
    Informations forums :
    Inscription : mars 2010
    Messages : 308
    Points : 793
    Points
    793

    Par défaut

    Citation Envoyé par Marc.Samuro Voir le message
    En ce qui concerne l'arithmétique de pointeurs, elle n'est tout simplement pas autorisée.
    Bon, je suis désolé, mais ceci achève de détruire définitivement toute crédibilité à ton "langage". Dire que c'est "exactement comme le C sauf que c'est safe", alors que tu n'autorise pas l'arithmétique de pointeur, je suis désolé, mais c'est une grosse blague. Il reste quoi comme intéret au C par rapport aux autres langages si tu ne peux pas faire d'arithmétique de pointeur ?

  17. #57

    Inscrit en
    janvier 2011
    Messages
    30
    Détails du profil
    Informations forums :
    Inscription : janvier 2011
    Messages : 30
    Points : -4
    Points
    -4

    Par défaut

    il faut poser la question autrement : comment cyclone rend-il l'incrémentation de pointeurs sûre ? en vérifiant chaque fois que le pointeur est toujours dans une zone mémoire donnée, par deux tests : p >= début && p < début + longueur. Il est bien plus économique d'utiliser un tableau et de ne faire qu'un seul test non-signé sur l'indice. En résumé : l'incrémentation de pointeur safe n'a plus aucun avantage sur les indices de tableaux.

  18. #58
    LLB
    LLB est déconnecté
    Membre Expert
    Inscrit en
    mars 2002
    Messages
    962
    Détails du profil
    Informations forums :
    Inscription : mars 2002
    Messages : 962
    Points : 1 128
    Points
    1 128

    Par défaut

    Bonjour,

    Voici mon premier programme de test. En Safe-C :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    int test()
    {
      int arr[100000];
      int i, j;
      int sum = 0;
     
      clear arr;
      for (i = 0; i < arr'length; i++)
        arr[i] = 2;
     
      for (j = 0; j < 1000; j++)
        for (i = 0; i < arr'length; i++)
          arr[i] = arr[i] + 1;
     
      for (i = 0; i < arr'length; i++)
        sum += arr[i];
     
      return sum;
    }
    Voici l'équivalent en C# (copié-collé à 90%) :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
            static int test()
            {
              int[] arr = new int[100000];
              int i, j;
              int sum = 0;
     
              for (i = 0; i < arr.Length; i++)
                   arr[i] = 2;
     
              for (j = 0; j < 1000; j++)
                for (i = 0; i < arr.Length; i++)
                   arr[i] = arr[i] + 1;
     
              for (i = 0; i < arr.Length; i++)
                   sum += arr[i];
     
              return sum;
            }
    Temps d'exécution sur ma machine :
    C# : 00.580 s
    Safe-C : 09.838 s

    Je retourne donc utiliser un langage "lourd et lent avec son garbage collector" (en vrai, j'utilise peu C#, mais c'était pour répondre à vos accusations).

  19. #59

    Inscrit en
    janvier 2011
    Messages
    30
    Détails du profil
    Informations forums :
    Inscription : janvier 2011
    Messages : 30
    Points : -4
    Points
    -4

    Par défaut

    touché ...
    apparemment j'ai encore pas mal de boulot pour optimiser les boucles ..

  20. #60
    LLB
    LLB est déconnecté
    Membre Expert
    Inscrit en
    mars 2002
    Messages
    962
    Détails du profil
    Informations forums :
    Inscription : mars 2002
    Messages : 962
    Points : 1 128
    Points
    1 128

    Par défaut

    Pour information, C# n'effectue pas de test sur l'indice quand il se rend compte statiquement que ça ne sert à rien. Si je boucle de 0 à Length, on sait qu'on ne dépasse pas du tableau. C'est une optimisation parmi beaucoup d'autres.

    J'espère que le compilateur remplace tous les arr'length par sa valeur, qui est connue statiquement. J'espère aussi que la boucle est effectuée l'envers (comparer un entier avec 0 est plus rapide qu'avec length), puisque le résultat ne change pas. J'espère que le clear ne fait rien, puisque je mets à 2 ensuite...

    Je serais admiratif si vous réussissez à battre C# en écrivant votre propre génération de code. C'est pour cette raison que j'ai conseillé dès le départ d'utiliser un backend éprouvé, comme LLVM. Vous pouvez aussi générer du code C et appeler un compilo C.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •