types de données efficaces et sécurisés en c++
TRANSCRIPT
Types de données efficaces et sécurisésen C++
Nicolas Burrus <[email protected]>
Séminaire du LRDE, 25 Septembre 2002
Table des matières
Table des matières
Introduction ............................................................................ 3
Contexte ............................................................................... 4
Problématique........................................................................ 5
Approches existantes ........................................................... 7
Matlab - Octave ...................................................................... 8
Vigra .................................................................................... 9
Ada...................................................................................... 12
Ancienne version d’Olena ......................................................... 13
Bilan global ........................................................................... 15
Besoins et objectifs ............................................................... 16
Ce qu’on aimerait ................................................................... 17
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 1
Table des matières
Que veut-on pour les types ? ..................................................... 18
Implémentation en C++ ......................................................... 19
Hiérarchie des scalaires ........................................................... 20
Organisation globale ............................................................... 21
Les opérateurs arithmétiques .................................................... 23
Les types de retour des opérations arithmétiques .......................... 27
La sécurité ............................................................................ 28
Ecrire un décorateur fonctionnel................................................. 29
Exemple de décorateur ............................................................ 30
Bilan ........................................................................................ 32
Par rapport à l’ancienne Olena .................................................. 33
Perspectives .......................................................................... 34
Conclusion ............................................................................ 36
Questions ? ........................................................................... 37
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 2
Introduction
Introduction
Types de données ?
• Scalaires. Entiers, flottants
• Complexes. Réprésentation polaire, rectangulaire
• Types énumérés. Type binaire, labels
• Types vectoriels. Vecteurs, matrices
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 3
Introduction Contexte
Contexte
• Bibliothèque Olena⇒ Langage C++⇒ Algorithmes génériques
• Calcul scientifique⇒ Besoin de fiabilité⇒ Besoin de performances
• Traitement d’images⇒ Chargement d’images en mémoire⇒ Utilisation intensive des types de données
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 4
Introduction Problématique
Problématique
• Types builtins du C++ dangereux
. Aucune vérification d’intervalle aux affectations
i n t i = 2 5 6 ;unsigned char c = i ; / / c == 0
. Opérations arithmétiques sans contrôles
unsigned i n t i = UINT_MAX;unsigned i n t j = 5 ;unsigned long long k = i + j ; / / k == 4
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 5
Introduction Problématique
• Algos génériques vis-à-vis des types de données :
template < class DataType>ResultType Sum( const Image<DataType >& ima ){
ResultType s = zero_for_Resul tType ( ) ;Image : : i t e r i ( ima ) ;
f o r _ a l l ( i )s += ima [ i ] ;
return s ;}
DataType trop petit pour la somme⇒ Quel est le type de ResultType ?
Comment écrire zero for ResultType() ?
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 6
Approches existantes
Approches existantes
• Approche naive avec les builtins ne convient pas
• Autres approches intéressantes :
. Matlab/Octave
. Vigra
. Ada
. Ancienne Olena
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 7
Approches existantes Matlab - Octave
Matlab - Octave
• Un seul type scalaire numérique : nombre à double précision
Bilan
⊕ Sécurité⊕ Simplicité
Occupation mémoire Temps CPU
⇒ Mal adapté au traitement d’images
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 8
Approches existantes Vigra
Vigra
• Utilise uniquement les builtins du C++
• Utilise des “traits”, caractéristiques associées à un ou plu-sieurs types, par exemple :
template < class T> s t ruc t l a r g e r _ t r a i t s ;
template < > s t ruc t l a r g e r _ t r a i t s <char > {typedef short l a rge r_ t ype ;
} ;
template < > s t ruc t l a r g e r _ t r a i t s < f l oa t > {typedef double l a rge r_ t ype ;
} ;
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 9
Approches existantes Vigra
Une somme générique avec Vigra s’écrit :
template < class DataType>typename v i g ra : : Numer icTrai ts <typename DataType > : : PromoteSum( const Image<DataType >& ima ){
typedef typename v i g ra : : Numer icTrai ts <typename DataType > : : Promote ResultType ;ResultType s ;Image : : i t e r i ( ima ) ;
s = v i g r a : : Numer icTrai ts <ResultType > : : zero ( ) ;f o r _ a l l ( i )s += ima [ i ] ;
return s ;}
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 10
Approches existantes Vigra
Vigra - Bilan
⊕ Permet des algos génériques⊕ Simplicité
Aucune vérification des débordements Traits fastidieux à écrire (2500 lignes de code pour les builtins)
⇒ Ne remplit pas nos contraintes de sécurité
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 11
Approches existantes Ada
Ada
• Vérification des débordements à l’exécution
• Peut ajouter des contraintes :
day : I n tege r range 1 . . 3 1 ;day := 32; −− Leve une except ion a l ’ execut ion
Bilan
⊕ Sécurité⊕ Contraintes
Ne permet pas de rajouter nos propres contraintes Surcoût à l’exécution
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 12
Approches existantes Ancienne version d’Olena
Ancienne version d’Olena
• Nouveaux types : int u<nbits>, sfloat, ...
• Vérifications statiques
Bilan
⊕ Contrôle des types⊕ Pas de surcoût à l’exécution
Temps de compilation Typage statique trop contraignant :
i n t_u <8> i = 5 ;in t_u <8> j = 2 ;in t_u <8> k = i + j ; / / Ne compile pas d i rec tement ( i + j ) es t un in t_u <9>
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 13
Approches existantes Ancienne version d’Olena
Bilan (suite)
Algos incompatibles avec les builtins
template < class T>T average ( const l i s t <T>& l ){
/ / Ne compile pas avec T == b u i l t i ntypedef typename T : : l a rge r_ t ype la rge r_ t ype ;l a rge r_ t ype sum = la rge r_ t ype : : zero ( ) ;/ / . . .
}
⇒ Utilisation lourde
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 14
Approches existantes Bilan global
Bilan global
Que nous apportent ces solutions ?
• Algos génériques avec intégration des builtins⇒ Vigra
• Vérifications des données à l’exécution⇒ Ada
• Typage fort et vérifications statiques⇒ Ancienne Olena
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 15
Besoins et objectifs
Besoins et objectifs
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 16
Besoins et objectifs Ce qu’on aimerait
Ce qu’on aimerait
• Sécurité⇒ Contrôle des débordements
• Efficacité⇒ Occupation mémoire minimale⇒ Vitesse d’exécution optimale⇒ Version “release” sans sécurité à l’exécution
• Généricité⇒ Ecriture simple d’algos génériques⇒ Interopérabilité avec les builtins
• Extensibilité⇒ Ajout de nouveaux types aisé
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 17
Besoins et objectifs Que veut-on pour les types ?
Que veut-on pour les types ?
• 1 type ⇔ une classe
. Ses variations ⇔ paramètres template
. Exemple : Entier non signé int_u
. Nombre de bits : int_u<8>
. Comportement : int_u<8,strict>
• On veut les propriétés classiques
. Opérations arithmétiques
. Conversions “naturelles”
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 18
Implémentation en C++
Implémentation en C++
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 19
Implémentation en C++ Hiérarchie des scalaires
Hiérarchie des scalaires
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 20
Implémentation en C++ Organisation globale
Organisation globale
On cherche à orthogonaliser le code au maximum
⇒ 3 hiérarchies parallèles :
• Valeurs : rec_value
. Stockage
• Types : typetraits<T>
. Définit les caractéristiques relatives au type : larger_type , cumul_type , ...
• Opérations : optraits<T>
. Traits fonctionnels : zero() , min() , ...
Cette division permet :
• L’intégration des builtins dans 2 hiérarchies
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 21
Implémentation en C++ Organisation globale
• L’écriture d’algos génériques
• Une meilleure souplesse dans le code
• Simplifications des types décorateurs⇒ Redéfinition d’une partie des classes uniquement
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 22
Implémentation en C++ Les opérateurs arithmétiques
Les opérateurs arithmétiques
On veut factoriser les opérations pour tous les scalaires.
On aimerait écrire (1) :
template < class T1 , class T2>returnTypeoperator +( const rec_sca lar <T1>& lhs ,
const rec_sca lar <T2>& rhs ){
/ / value ( ) es t une methode qui renvo ie l a va leurreturn l hs . value ( ) + rhs . value ( ) ;
}
Mais on veut gérer les builtins !
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 23
Implémentation en C++ Les opérateurs arithmétiques
On rajoute (2) ...
template < class T1 , class B2>returnTypeoperator +( const rec_sca lar <T1>& lhs ,
const B2& rhs ){
return l hs . value ( ) + rhs ;}
et (3) :
template < class B1 , class T2>returnTypeoperator +( const B1& lhs ,
const rec_sca lar <T2>& rhs ){
return l hs + rhs . value ( ) ;}
Aie ! Ambigü pour le compilateur.
• Exemple : int_u + int_u
. Identification à un argument template prioritaire sur la relation d’héritage⇒ (2) et (3) sont prioritaires sur (1)⇒ Conflit entre (2) et (3)
On veut mettre une contrainte sur B1 et B2 pour les limiter aux builtins.
Donnons nous une classe universelle :
template < class T>s t ruc t anyClass
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 24
Implémentation en C++ Les opérateurs arithmétiques
{anyClass (T& t ) : _ ta rge t ( t ) { }T& s e l f ( ) { return _ ta rge t ; }T& _ ta rge t ;
} ;
Finalement on peut réécrire (2) (de même pour (3)) :
template < class T1 , class T2>returnType operator +( const rec_sca lar <T1>& lhs , const anyClass <T2>& rhs ){
return l hs . value ( ) + rhs . s e l f ( ) ;}
Construire une anyClass par conversion difficile⇒ plus d’ambiguité
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 25
Implémentation en C++ Les opérateurs arithmétiques
Problème : le compilateur ne peut déduire T2 tout seul⇒ il faut instancier explicitement la fonction par un opérateur “proxy” global
template < class T1 , class T2>returnTypeopera tor_p lus ( const rec_sca lar <T1>& lhs ,
const anyClass <T2>& rhs ){
return l hs . value ( ) + rhs . s e l f ( ) ;}
template < class T1 , class T2>returnTypeopera tor_p lus ( const anyClass <T1>& rhs ,
const rec_sca lar <T2>& rhs ){
return l hs . s e l f ( ) + rhs . value ( ) ;}
template < class T1 , class T2>returnTypeopera tor_p lus ( const rec_sca lar <T1>& rhs ,
const rec_sca lar <T2>& rhs ){
return l hs . value ( ) + rhs . value ( ) ;}
/ / operateur g loba l proxytemplate < class T , class U>returnTypeoperator + ( const T& lhs ,
const U& rhs ){
return operator_p lus <T ,U>( lhs , rhs ) ;}
Ce code n’est écrit qu’une seule fois pour tous les sca-laires !
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 26
Implémentation en C++ Les types de retour des opérations arithmétiques
Les types de retour des opérations arithmétiques
• Traits binaires pour les définir
• Les types grossissent, par exemple :int_u<8> + int_u<8> ⇒ int_u<9>
int_s<8> * int_u<8> ⇒ int_s<17>
⇒ Permet un typage fin
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 27
Implémentation en C++ La sécurité
La sécurité
• Vérifications statiques si possible ...
i n t_u <7> i = 5 ;in t_u <7> j = 5 ;in t_u <8> k = i ; / / ok , on s a i t que ca ren t re ra , pas de t e s t sk = i + j ; / / ok , on s a i t que ca ren t re ra , pas de t e s t s
• ... à l’exécution sinon
i n t_u <8> i = 5 ;in t_u <8> j = 5 ;in t_u <8> k = i + j ; / / asser t ( ( i + j ) <= o p t r a i t s < in t_u <8 > >::max ( ) )
⇒ Finalement, vitesse maximale
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 28
Implémentation en C++ Ecrire un décorateur fonctionnel
Ecrire un décorateur fonctionnel
• Hiérarchie de valeur : presque rien⇒ Définition des constructeurs/destructeurs⇒ Opérateurs de cast
• Hiérarchie de type : presque rien⇒ Proxy vers les caractéristiques du type décoré
• Hiérarchie d’opérations : juste les fonctions nouvelles/modi-fiées⇒ L’héritage apporte toutes les opérations par défaut
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 29
Implémentation en C++ Exemple de décorateur
Exemple de décorateur
Prenons par exemple range<T,Interval,Behaviour> :
/ / h i e r a r c h i e de va leurstemplate < class T , class I n t e r v a l , class Behaviour >s t ruc t range : publ ic rec_sca lar <T , I n t e r v a l , Behaviour > {
range ( const T& lhs ) { _value = lhs ; }/ / . . . Autres cons t ruc teu rs e t operateur de cast
} ;
/ / h i e r a r c h i e de typestemplate < class T , class I n t e r v a l , class Behaviour >s t ruc t t y p e t r a i t s <range<T , I n t e r v a l , Behaviour > : publ ic t y p e t r a i t s <T > {
typedef typename t y p e t r a i t s <T > : : l a rge r_ t ype la rge r_ t ype ;/ / l e res te des typedefs proxy
} ;
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 30
Implémentation en C++ Exemple de décorateur
Finalement, la hiérarchie d’opérations
/ / h i e r a r c h i e d ’ opera t ionstemplate < class T , class I n t e r v a l , class Behaviour >s t ruc t o p t r a i t s <range<T , I n t e r v a l , Behaviour > : publ ic o p t r a i t s <T > {
typedef I n t e r v a l : : re tu rn_ type i n t e r v a l _ t y p e ;s t a t i c i n t e r v a l _ t y p e min ( ) { return I n t e r v a l : : min ( ) ; }s t a t i c i n t e r v a l _ t y p e max ( ) { return I n t e r v a l : : max ( ) ; }
} ;
On peut maintenant écrire :
range< in t , bounded_s <−10 , 10 > , sa tura te > r1 = −30; / / vaut −10range<int_u8 , bounded_u <0 , 10 > , s t r i c t > r2 = 5 ;
s td : : cout < < ( r1 + r2 ) < < std : : endl ;
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 31
Bilan
Bilan
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 32
Bilan Par rapport à l’ancienne Olena
Par rapport à l’ancienne Olena
• Gains. Sécurité
. Types décorés - possibilité d’extension
. Intégration des builtins
. Factorisation du code
. Simplicité d’utilisation
• Problèmes conservés. Temps de compilation
. Code complexe
. Débuggage difficile
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 33
Bilan Perspectives
Perspectives
• Extension, implémentation de plus de types
• Ajout de caractéristiques mathématiques⇒ Héritage conditionnel vers les structures algébriques cor-respondantes
• Amélioration de la gestion des décorateurs⇒ Meilleure intégration à la hiérarchie⇒ Plus de généricité, exemple :
s t ruc t cmp_inf : publ ic s td : : b ina ry_ func t i on <vec<N, T> , vec<N, T> , bool > {bool operator ( ) ( const vec<N, T>& lhs , const vec<N, T>& rhs ) const{ return ( l hs [ 0 ] < rhs [ 0 ] ) ; }
} ;
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 34
Bilan Perspectives
i n t main ( ) {r e l a t i o n a l _ d e c o r a t o r <vec <3 , in t > , cmp_inf > v1 ;v1 [ 0 ] = 5 ;/ / . . . f i n de l ’ i n i t de v1r e l a t i o n a l _ d e c o r a t o r <vec <3 , in t > , cmp_inf > v2 ;/ / i n i t de v2
i f ( v1 < v2 ){
s td : : cout < < ‘ ‘ Youpi ! ’ ’ < < s td : : endl ;}
}
Problème : mauvaise intégration des décorateurs
⇒ On ne peut pas écrire un relational_decorator qui fonc-tionne pour tous les types.
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 35
Bilan Conclusion
Conclusion
• Solution qui permet plus de choses
• Conserve un certain nombre de problèmes
• Migration d’Olena en cours
• Devrait être distribué séparément d’Olena.
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 36
Bilan Questions ?
Questions ?
Types de données efficaces et sécurisés en C++, Nicolas Burrus - Séminaire du LRDE, 25 Septembre 2002 37