Précédent   Forum du club des développeurs et IT Pro > C et C++ > C > Contribuez
Contribuez Proposez vos articles, cours, tutoriels, FAQ, sources, et autres ressources pour la rubrique C.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 24/01/2011, 17h23   #41
Marc.Samuro
 
Inscription : janvier 2011
Messages : 30
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 30
Points : -4
Points : -4
Citation:
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);
Marc.Samuro est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/01/2011, 19h02   #42
gl
Rédacteur/Modérateur
 
Homme
Inscription : juin 2002
Messages : 2 034
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 34
Localisation : France, Hauts de Seine (Île de France)

Informations forums :
Inscription : juin 2002
Messages : 2 034
Points : 3 828
Points : 3 828
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 ?
gl est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/01/2011, 02h15   #43
souviron34
Expert Confirmé Sénior
 
Inscription : janvier 2007
Messages : 9 569
Détails du profil
Informations personnelles :
Âge : 55

Informations forums :
Inscription : janvier 2007
Messages : 9 569
Points : 11 849
Points : 11 849
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
souviron34 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 25/01/2011, 04h45   #44
Marc.Samuro
 
Inscription : janvier 2011
Messages : 30
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 30
Points : -4
Points : -4
Citation:
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.

Citation:
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};
Marc.Samuro est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/01/2011, 05h38   #45
Marc.Samuro
 
Inscription : janvier 2011
Messages : 30
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 30
Points : -4
Points : -4
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'.
Marc.Samuro est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/01/2011, 10h01   #46
jack-ft
Membre Expert
 
Inscription : avril 2008
Messages : 794
Détails du profil
Informations forums :
Inscription : avril 2008
Messages : 794
Points : 1 800
Points : 1 800
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(
jack-ft est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/01/2011, 15h43   #47
TropMDR
Membre chevronné
 
Inscription : mars 2010
Messages : 281
Détails du profil
Informations forums :
Inscription : mars 2010
Messages : 281
Points : 752
Points : 752
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.
TropMDR est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/01/2011, 18h58   #48
Marc.Samuro
 
Inscription : janvier 2011
Messages : 30
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 30
Points : -4
Points : -4
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 ..
Marc.Samuro est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/01/2011, 20h17   #49
TropMDR
Membre chevronné
 
Inscription : mars 2010
Messages : 281
Détails du profil
Informations forums :
Inscription : mars 2010
Messages : 281
Points : 752
Points : 752
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
TropMDR est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/01/2011, 00h43   #50
Marc.Samuro
 
Inscription : janvier 2011
Messages : 30
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 30
Points : -4
Points : -4
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 ..
Marc.Samuro est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/01/2011, 19h00   #51
TropMDR
Membre chevronné
 
Inscription : mars 2010
Messages : 281
Détails du profil
Informations forums :
Inscription : mars 2010
Messages : 281
Points : 752
Points : 752
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 :-\
TropMDR est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 27/01/2011, 20h20   #52
TropMDR
Membre chevronné
 
Inscription : mars 2010
Messages : 281
Détails du profil
Informations forums :
Inscription : mars 2010
Messages : 281
Points : 752
Points : 752
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 !
TropMDR est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/01/2011, 22h56   #53
Marc.Samuro
 
Inscription : janvier 2011
Messages : 30
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 30
Points : -4
Points : -4
Citation:
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.

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

Citation:
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.

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

Citation:
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' ..

Citation:
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

Citation:
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.

Citation:
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.

:-)
Marc.Samuro est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/01/2011, 23h18   #54
TropMDR
Membre chevronné
 
Inscription : mars 2010
Messages : 281
Détails du profil
Informations forums :
Inscription : mars 2010
Messages : 281
Points : 752
Points : 752
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.
TropMDR est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/01/2011, 23h27   #55
Marc.Samuro
 
Inscription : janvier 2011
Messages : 30
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 30
Points : -4
Points : -4
Citation:
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

Citation:
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à.
Marc.Samuro est déconnecté   Envoyer un message privé Réponse avec citation 01
Vieux 27/01/2011, 23h37   #56
TropMDR
Membre chevronné
 
Inscription : mars 2010
Messages : 281
Détails du profil
Informations forums :
Inscription : mars 2010
Messages : 281
Points : 752
Points : 752
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 ?
TropMDR est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 27/01/2011, 23h43   #57
Marc.Samuro
 
Inscription : janvier 2011
Messages : 30
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 30
Points : -4
Points : -4
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.
Marc.Samuro est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/01/2011, 23h52   #58
LLB
Membre Expert
 
Inscription : mars 2002
Messages : 962
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 962
Points : 1 148
Points : 1 148
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).
LLB est déconnecté   Envoyer un message privé Réponse avec citation 50
Vieux 28/01/2011, 00h06   #59
Marc.Samuro
 
Inscription : janvier 2011
Messages : 30
Détails du profil
Informations forums :
Inscription : janvier 2011
Messages : 30
Points : -4
Points : -4
touché ...
apparemment j'ai encore pas mal de boulot pour optimiser les boucles ..
Marc.Samuro est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/01/2011, 00h17   #60
LLB
Membre Expert
 
Inscription : mars 2002
Messages : 962
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 962
Points : 1 148
Points : 1 148
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.
LLB est déconnecté   Envoyer un message privé Réponse avec citation 20
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 02h18.


 
 
 
 
Partenaires

Hébergement Web