[résolu]Sécurisé son code - iterator

K-lo
[résolu]Sécurisé son code - iterator

Voilà je cherche à sécuriser mon code pour repérer un éventuel dépassement de la mémoire lorsque j'utilise un iterator d'un vector (par exemple) :

function copieApreTraitements(std::vector _v){
std::vector v1, v2;
//Traitements
v1.assign(_v.begin(), _v.begin() + 8);  // risque ici
//Traitements
v2.assign(_v.begin()+8, _v.end()); // risque ici
}

Cette fonction n'est qu'un exemple et les traitements intermédiaires n'ont rien à voir avec ma question.
Mais en utilisant cette fonction avec comme parametre un vector dont le nombre d'entrée est de 4, je vais produire une très jolie erreur de dépassement de mémoire. j'ai essayer un bloc try - catch mais ça n'a pas l'air de relever une exception :?
Je pourrais tester la taille du vector passé en argument de ma fonction mais là n'est pas le but de ma question.

Ce que j'aimerais si possible, c'est d'avoir un comportement simillaire à la méthode at() d'un vector (sachant que at() n'as pas grand chose a voir avec les iterator je me retrouve un peu coincé). :oops:

Sans pour autant passer à JAVA :lol: :lol: :lol:

fredericmazue

Deux remarques, si tu me le permets

std::vector<le_type> _v

Tu ne devrais pas appeler une variable _V, c'est à dire commençant par un underscore (souligné). Ce type de dénomination est réservé à l'implémentation. Si tu veux mettre un souligné c'est:

std::vector<le_type> v_

Ensuite
copieApreTraitements(std::vector _v)
Je sais bien que tu as écrit du pseudo code, mais je ne peux m'empêcher de te dire que tu ne devrais pas passer le vector par valeur. Si tu le fais, il y a copie du vector et de tous les éléments qui sont dedans. Je sais bien qu'on va encore me dire que je fais un buzz sur la charge ;) mais je préfère un passage par référence :) Donc:

copieApreTraitements(std::vector<le_type>& v_

Quote:
Mais en utilisant cette fonction avec comme parametre un vector dont le nombre d'entrée est de 4, je vais produire une très jolie erreur de dépassement de mémoire.

En effet
Quote:
j'ai essayer un bloc try - catch mais ça n'a pas l'air de relever une exception

En aucun cas ça ne va lever une exception. Les conteneurs de la stl ne sont pas conçu dans cet esprit. On est pas en Java là :)

Quote:
Je pourrais tester la taille du vector passé

Oui. Mais si tu ne veux pas le faire, alors deux solutions, dans l'ordre de mes préférences.

- repenser ton code pour ne pas te trouver dans cette situation que je trouve étrange. Mais bon j'ai peut être tort. Je n'ai pas de vision d'ensemble de ce que tu fais.

- Ecrire le conteneur que tu veux avec les itérateurs ayant le comportement que tu veux. Dans ton cas, cela revient à définir un opérateur d'addition qui lève une exception en cas de dépassement.

Attention hein, j'ai dit opérateur d'addition, parce que je parle de ton pseudo code. Pour le code complet du conteneur et des itérateurs, il y a plus de travail. C'est difficile d'écrire un conteneur et c'est d'ailleurs pour cela que la première solution est la meilleure :)

Quote:
Sans pour autant passer à JAVA

T'as pas intérêt, sinon j'te cause plus :lol:
K-lo

fredericmazue wrote:
Deux remarques, si tu me le permets

std::vector<le_type> _v

Tu ne devrais pas appeler une variable _V, c'est à dire commençant par un underscore (souligné). Ce type de dénomination est réservé à l'implémentation. Si tu veux mettre un souligné c'est:

std::vector<le_type> v_

J'étais pas au courant :? et je te permet :lol:

fredericmazue wrote:

Ensuite
copieApreTraitements(std::vector _v)
Je sais bien que tu as écrit du pseudo code, mais je ne peux m'empêcher de te dire que tu ne devrais pas passer le vector par valeur. Si tu le fais, il y a copie du vector et de tous les éléments qui sont dedans. Je sais bien qu'on va encore me dire que je fais un buzz sur la charge ;) mais je préfère un passage par référence :) Donc:

copieApreTraitements(std::vector<le_type>& v_

Effectivement c'est mieu comme ça :?

fredericmazue wrote:

Quote:
Je pourrais tester la taille du vector passé

Oui. Mais si tu ne veux pas le faire, alors deux solutions, dans l'ordre de mes préférences.

Oui bah jevais peut être revenir a ce test :P

fredericmazue wrote:

- Ecrire le conteneur que tu veux avec les itérateurs ayant le comportement que tu veux. Dans ton cas, cela revient à définir un opérateur d'addition qui lève une exception en cas de dépassement.

Attention hein, j'ai dit opérateur d'addition, parce que je parle de ton pseudo code. Pour le code complet du conteneur et des itérateurs, il y a plus de travail. C'est difficile d'écrire un conteneur et c'est d'ailleurs pour cela que la première solution est la meilleure :)


la bibliothèque boost à defini l'opérateur += dans la class assign... pour les conteneurs de la STL mais j'ai pas "encore" trouvé la bonne utilisation pour mon cas...

fredericmazue wrote:

Quote:
Sans pour autant passer à JAVA

T'as pas intérêt, sinon j'te cause plus :lol:
:lol:
fredericmazue

Quote:
la bibliothèque boost à defini l'opérateur += dans la class assign... pour les conteneurs de la STL mais j'ai pas "encore" trouvé la bonne syntaxe pour mon cas...

Ah mais je ne crois pas que ça soit la même chose. Dans Boost il s'agit d'une surcharge de opérator +=() et aussi de operator,() je crois, pour aboutir à des sucres syntaxiques de ce genre:

vector<int> values;  
values += 1,2,3,4,5,6,7,8,9;

Mais au final je suppose que le code effectue de vulgaires push_back pour remplir le vector. Nous sommes loin de la sécurisation de operator[]() là. Faudrait regarder les sources de Boost pour le vérifier toutefois.

K-lo

Quote:
h mais je ne crois pas que ça soit la même chose. Dans Boost il s'agit d'une surcharge de opérator +=() et aussi de operator,() je crois, pour aboutir à des sucres syntaxiques

C'est ce dont j'avais peur :?
Mais pour ce qui est de la sécurisation, cette méthode releve une exception en cas d'erreur donc je vais approfondir ma recherche a ce propos mais effectivement ça semble pas correspondre au problème...
K-lo

bon j'ai rien trouvé avec boost:?
Je me retourne vers la méthode du test de la taille

try{
if((int)v.size() < (pos-1) ){ //-1 : voir assign 
   throw(1);
}
v1.assign(v.begin(), v.begin()+pos); 
}catch(...){
//code 
}
fredericmazue

Ca devrait être
catch(int code_erreur) // etc

Et je ne suis pas sûr que lever une exception soit le bon traitement. Pourquoi pas un simple:

if((int)v.size() < (pos-1) ){ //-1 : voir assign
  return false;
}

Il y a fréquemment des débats entre gurus C++ pour savoir s'il est mieux de lever une exception ou de retourner un code d'erreur. Le sujet est souvent assez délicat. Mais dans ton cas, pour le peu que j'en sais, je pencherais plutôt pour le code de retour.
Dans ce cas, j'irais même plus loin: faire le test en amont de l'appel à copieApresTraitements

K-lo

Très bien merci pour tous ces conseils !

fredericmazue

Au fait, c'est même
copieApreTraitements(const std::vector<le_type>& v_)
qu'il faudrait écrire.

K-lo

C'est noté :) :!: Merci (bon c'est bon je passerai pas sur JAVA :D)