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

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

 C++ Discussion :

au sujet de l'intérêt des bonnes pratiques


Sujet :

C++

  1. #21
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Crois tu vraiment que le fait de devoir vérifier s'il te reste suffisemment de place pour effectuer la concaténation et devoir réallouer de la mémoire le cas échéans soit facile
    Ca dépend des cas bien entendu. Mais quand tu as, par exemple, 4 ou 5 char* que tu dois concaténer, tu peux facilement obtenir leurs tailles et les additionner. C'est très mineur évidemment...
    Edit: en réponse au message d'Arzar, que je viens de voir, on pourrait simplement imaginer cette solution écrite à la va-vite:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int main(void) {
    	const char* str1 = "Hello";
    	const char* str2 = " ";
    	const char* str3 = "World !";
     
    	int len1 = strlen(str1);
    	int len2 = strlen(str2);
    	int len3 = strlen(str3);
     
    	char* strConcat = malloc(len1 + len2 + len3 + 1);
    	char* ptr = strConcat;
     
    	memcpy(ptr, str1, len1);
    	ptr += len1;
     
    	memcpy(ptr, str2, len2);
    	ptr += len2;
     
    	memcpy(ptr, str3, len3);
    	ptr[len3] = '\0';
     
    	printf("%s\n", strConcat);
     
    	return 0;
    }
    Ou si tu préfères la version fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    char* concat(const char** array, int size) {
    	int lengths[size];
    	int total = 0;
    	int cur;
    	int i;
     
    	char* result;
    	char* ptr;
     
    	for(i = 0; i < size; ++i) {
    		cur = strlen(array[i]);
    		lengths[i] = strlen(array[i]);
    		total += cur;
    	}
     
    	result = malloc(total + 1);
     
    	for(i = 0, ptr=result; i < size; ++i) {
    		memcpy(ptr, array[i], lengths[i]);
    		ptr += lengths[i];
    	}
     
    	*ptr = '\0';
    	return result;
    }
     
    int main(void) {
    	const char* array[4] = {
    		"Hello",
    		" ",
    		"World",
    		" !"
    	};
     
    	char* result = concat(array, 4);
     
    	printf("%s\n", result);
     
    	free(result);
    	return 0;
    }
    Peut être simplement les opérateurs + et += redéfinis pour la classe string, qui fonctionnent aussi très bien avec des char*
    Si si, je les connais Mais je leur reproche de faire une allocation à chaque concaténation.

    Fais déjà attention à la différence (effectivement subtile) qui existe entre la SL (qui contient entre autre la classe string) et la STL qui manipule les modèle
    Ah, je ne savais pas que c'était en 2 packages... Y a-t-il un lien qui me permette de savoir quoi appartient à quoi ?

    Je n'ai, à mon grand dam, encore jamais eu l'occasion de travailler dans l'embarqué, mais, en théorie, l'utilisation des modèles ne devrait pas vraiment avoir d'impact particulier par rapport à une structure identique "classsique" étant donné que tout est fait au moment de la compilation...
    Mais on dit souvent que la stl est plus lourde à l'exécution, vu qu'elle doit être robuste et servir à tout usage. Est-ce vrai, ou sont-ce des rumeurs stupides de détracteurs du Cpp ?
    Je serais d'ailleurs intéressé par un lien détaillant le fonctionnement interne des types de la stl.

    La bonne question étant de savoir si, effectivement, la structure même des collections de la STL sont intéressante en embarqué... et, sur ce point, je ne suis pas en mesure de faire ma propre idée
    Il n'y a pas grandes différences à première vue, si ce n'est les restrictions de mémoire, de puissance de calcul, de set d'opération (cpu de type risc), et surement d'autres choses dont je n'ai même pas idée.

    Cela dit, je suis jeune développeur, et ça fait fort peu de temps que je bosse dans les systèmes embarqués. J'en connais trop peu pour pouvoir dire si oui ou non la structure de la stl est appropriée. Il est possible que je fasse complètement fausse route. Si c'est le cas j'apprécierais grandement que quelqu'un me remette sur la bonne voie

  2. #22
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par Antoine_935 Voir le message
    Si si, je les connais Mais je leur reproche de faire une allocation à chaque concaténation.
    Bien que je n'ai jamais regardé le fonctionnement interne en détail, je peux t'assurer que ce n'est pas forcément vrai:

    C'est la raison pour laquelle tu dispose de deux fonctions (capacity et size) renvoyant respectivement le nombre de caractères que peut contenir la chaine et le nombre de caractères utiles de la chaine

    De plus, tu as des fonctions comme resize qui te permet, si tu crains que les concaténation successives ne viennent à provoquer des allocations en nombre, mais que tu sais déterminer la taille finale, de forcer à allouer cette taille une bonne fois pour toute
    Ah, je ne savais pas que c'était en 2 packages... Y a-t-il un lien qui me permette de savoir quoi appartient à quoi ?
    En fait, ce ne sont pas vraiment deux "packages", c'est plutôt un ensemble et son sous ensemble...

    SL signifie "Standard Library" (autrement dit, tout ce qui fait partie de la bibliothèque standard), alors que STL signifie Standard Templated Library, c'est à dire tout ce qui fait appel au paradigme de programmation générique (utilisant les templates), et qui est fourni... par la SL
    Mais on dit souvent que la stl est plus lourde à l'exécution, vu qu'elle doit être robuste et servir à tout usage. Est-ce vrai, ou sont-ce des rumeurs stupides de détracteurs du Cpp ?
    Il est vrai que la S(T)L doit être robuste et servir pour tout usage.

    Par contre, de là à dire qu'elle est lourde à l'exécution, il y a un pas que je me garderai bien de franchir:

    Bien sûr, elle doit fournir une série de fonctions qui ne te serviront peut être pas dans un projet donné, mais la robustesse du code devrait de toutes manières être un de tes objectifs primordiaux, même si tu travailles en embarqué

    Et, il faut avouer que lorsqu'une bibliothèque est utilisée par des millions de gens dont des milliers qui vont poser les yeux dessus, tu as beaucoup plus de chances d'avoir un code robuste que si tu essaye d'en reproduire le fonctionnement seul dans ton coin

    Maintenant, il est aussi vrai que si tu n'utilise pas les bonnes méthodes qui te sont offertes par la STL, tu peux facilement en arriver à voir les performances chuter dans un rapport de 1 pour 4 voir pis encore
    Je serais d'ailleurs intéressé par un lien détaillant le fonctionnement interne des types de la stl.
    L'avantage de la STL, c'est qu'elle utilise les modèles, et que, pour que le compilateur soit en mesure de créer le code exécutable en fonction d'un type particulier, il doit disposer des fonctions qui utilisent des modèles

    Cela signifie que les fonctions de la STL sont, quoi qu'il arrive, définies ou inclues directement dans le fichier d'en-tête

    Si tu veux en savoir plus sur le fonctionnement interne de la STL, tu n'a donc, en gros, qu'à ouvir le fichier d'en-tête (ou le fichier d'implémentation inclus par le fichier d'en-tête) de la classe que tu souhaites étudier

    Il n'y a pas grandes différences à première vue, si ce n'est les restrictions de mémoire,
    Ca, ca peut effectivement représenter un problème ... Mais tu cours le même en créant tes propres structures
    de puissance de calcul,
    Ca, par contre, cela ne devrait avoir qu'un incidence sur le délais qu'il faut pour obtenir un résultat...

    Et un mauvais algorithme aura surement une incidence bien plus importante

    Or, justement, l'utilisation de modèles permet de définir ce que l'on appelle des politiques, c'est à dire, des comportements qui seront adaptés aux différentes situations (car un algorithme peut être génial dans certains cas et exécrable dans d'autres )
    de set d'opération (cpu de type risc),
    Mais ca, ce n'est clairement pas de ton ressort: c'est du ressort du compilateur que de transformer ton code en une succession de 0 et de 1 que le cpu comprendra
    Cela dit, je suis jeune développeur, et ça fait fort peu de temps que je bosse dans les systèmes embarqués. J'en connais trop peu pour pouvoir dire si oui ou non la structure de la stl est appropriée. Il est possible que je fasse complètement fausse route. Si c'est le cas j'apprécierais grandement que quelqu'un me remette sur la bonne voie
    Tu l'auras compris, je ne suis pas réellement en mesure de parler d'une autre manière que "purement théorique"
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #23
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Citation Envoyé par koala01 Voir le message
    De plus, tu as des fonctions comme resize qui te permet, si tu crains que les concaténation successives ne viennent à provoquer des allocations en nombre, mais que tu sais déterminer la taille finale, de forcer à allouer cette taille une bonne fois pour toute
    Ah ? J'y jetterai un oeuil.

    STL signifie Standard Templated Library
    Eh mais ça change tout je croyais que c'était standard Type library...

    Si tu veux en savoir plus sur le fonctionnement interne de la STL, tu n'a donc, en gros, qu'à ouvir le fichier d'en-tête (ou le fichier d'implémentation inclus par le fichier d'en-tête) de la classe que tu souhaites étudier
    C'est dingue... voila pas mal de temps maintenant que je bosse énormément pour créer des templates, et ça ne m'est même pas venu à l'idée d'aller ressortir les .h de la stl...

    Ca, ca peut effectivement représenter un problème ... Mais tu cours le même en créant tes propres structures
    C'est justement la raison pour laquelle je préférais, jusqu'à présent du moins, faire mes propres structures: je peux facilement calculer, et même, dans certaines limites, définir la mémoire nécessaire.

    Et un mauvais algorithme aura surement une incidence bien plus importante
    Oui c'est vrai, mais pour créer des listes chaînées optimisées pour certaines opérations, c'est toujours plus ou moins le même algorithme.

    Mais ca, ce n'est clairement pas de ton ressort: c'est du ressort du compilateur que de transformer ton code en une succession de 0 et de 1 que le cpu comprendra
    C'est certain, je n'ai aucune envie de m'occuper de l'asm pour chaque architecture... Je voulais juste souligner le fait que certaines opérations pouvaient être plus ou moins performantes sur certaines architectures de cpu. Elles peuvent même être dépendantes du matériel disponible à côté. Dans mon cas, je dispose, entre autre, de matérial spécialisé pour les opérations trigo. On doit par contre y faire explicitement appel.

    Tu l'auras compris, je ne suis pas réellement en mesure de parler d'une autre manière que "purement théorique"
    Ca tombe bien, j'aime la théorie (mais uniquement dans le contexte de la programmation)

  4. #24
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par Antoine_935 Voir le message
    Ah ? J'y jetterai un oeuil.
    N'oublie pas d'aller le rechercher par la suite, sinon, tu auras des problèmes
    Eh mais ça change tout je croyais que c'était standard Type library...
    La STL est loin de ne présenter que des types...

    Regarde ce que te fournit l'en-tête <algorithm> pour t'en convaincre
    C'est dingue... voila pas mal de temps maintenant que je bosse énormément pour créer des templates, et ça ne m'est même pas venu à l'idée d'aller ressortir les .h de la stl...
    Mais, si, déjà, tu te trompais sur la signification du T... on peut comprendre que tu n'aies jamais fait le rapprochement
    C'est justement la raison pour laquelle je préférais, jusqu'à présent du moins, faire mes propres structures: je peux facilement calculer, et même, dans certaines limites, définir la mémoire nécessaire.
    Si tu as un doute au niveau de la taille mémoire de tes structures, tu peux toujours passer par sizeof
    Oui c'est vrai, mais pour créer des listes chaînées optimisées pour certaines opérations, c'est toujours plus ou moins le même algorithme.
    Oui, et parfaitement optimisé dans std::list< > par exemple (même si, elle, c'est une liste doublement chainée...)
    C'est certain, je n'ai aucune envie de m'occuper de l'asm pour chaque architecture... Je voulais juste souligner le fait que certaines opérations pouvaient être plus ou moins performantes sur certaines architectures de cpu. Elles peuvent même être dépendantes du matériel disponible à côté.
    Mais cela dépend uniquement de "l'intelligence" que le concepteur du compilateur aura pu lui donner par rapport au set d'instructions disponible

    Le compilateur est un brave petit soldat qui ne pose pas de question:

    Si, pour un arbre d'instructions données, on lui a dit de créer un code assembleur donné (modulo les inévitables informations variables qui vont apparaitre), il le fera quoi qu'il arrive
    Dans mon cas, je dispose, entre autre, de matérial spécialisé pour les opérations trigo. On doit par contre y faire explicitement appel.
    Si cela nécessite de passer par des instructions assembleur spécifiques, tu peux bien évidemment envisager de le faire

    (On pourrait presque conseiller de le faire dans ce cas d'ailleurs )

    Si, pour appeler ces opérations trigo, tu dispose de fonctions (C ou C++ style) particulières, dés le moment où elles sont déclarées, tu les utilise comme n'importe quelle autre fonction issue d'une bibliothèque extèrne
    Ca tombe bien, j'aime la théorie (mais uniquement dans le contexte de la programmation)
    Ce que je voulais dire, c'est qu'il peut y avoir des incompatibilités propres au matériel ou à l'embarqué qui sont de nature à invalider entièrement ce que je peux avoir écrit... Mais, ne les connaissant pas, j'aurai le plus grand mal à m'en rendre compte
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #25
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Je viens de mettre la main sur les fichiers d'en-tête
    Eh bah... je vais m'en servir de la stl... Je n'ai pas le niveau pour créer quelque chose de qualité équivalente...

    C'est dingue. J'ai lu 100 lignes, et appris déjà 3 choses. Appris que, par exemple, on pouvait mettre une directive "using" dans les champs protected d'une classe. Je ne m'en serais jamais douté.

    Puis bon, réflexion faite, ils font bien tourner du java sur des gsm, et je suis pas à 2Ko près sur mon système, donc je peux bien me permettre d'utiliser des listes doublement chaînées.

    J'ai un petit doute quant à la map par contre... je vais de ce pas en voir le fonctionnement interne
    Edit: c'est un arbre, et non une hashmap comme je le redoutais. Bonne nouvelle donc

    Pour résumer, je prenais les histoires de performances trop à coeur (comme beaucoup de débutants en fait...), et, la vache, j'ai encore une looooongue route à faire en cpp...


    Merci à toi pour toutes ces infos

    PS: à propos du java sur les gsm, j'ai vu récemment que certains processeurs ARM étaient pourvus d'une technologie qu'ils appellent "Jazelle". Elle permet d'exécuter environ 95% du bytecode java directement sur le cpu... impressionnant.

  6. #26
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par koala01 Voir le message
    De plus, tu as des fonctions comme resize qui te permet, si tu crains que les concaténation successives ne viennent à provoquer des allocations en nombre, mais que tu sais déterminer la taille finale, de forcer à allouer cette taille une bonne fois pour toute
    Petit détail, c'est reserve qui fait ça, resize changeant réellement la taille, en remplissant éventuellement les cases en trop par un caractère spécifié ou '\0'. Comme pour les vector : Reserve : Optimisation, resize : Comportement, et finalement assez rare d'emploi.
    Citation Envoyé par koala01 Voir le message
    En fait, ce ne sont pas vraiment deux "packages", c'est plutôt un ensemble et son sous ensemble...

    SL signifie "Standard Library" (autrement dit, tout ce qui fait partie de la bibliothèque standard), alors que STL signifie Standard Templated Library, c'est à dire tout ce qui fait appel au paradigme de programmation générique (utilisant les templates), et qui est fourni... par la SL
    Une autre version des choses consiste à dire que SL est la bibliothèque standard, clairement et officiellement définie par le standard. STL elle peut selon les cas désigner une bibliothèque de conteneurs initialement développée par Stepanov et Lee, ou une sous partie de la SL, aux frontières un peu floues, qui a été très fortement inspirée par ces conteneurs (en gros, conteneurs, algorithmes, itésateurs, mais pas iostream, même si ceux-ci sont templatés).

    Autrement, pour l'usabilité de la STL en environnement embarqué, quand je lis embarqué, je vois deux contraintes :
    - La rapidité du code (contrainte que je connais assez), et là, je ne vois pas forcément trop de problèmes à la STL, sauf qu'elle réalise parfois trop de copies, chose qui devrait s'arranger avec C++0x. Voir par exemple http://www.open-std.org/jtc1/sc22/wg...007/n2271.html pour une critique de la STL dans des environnements console de jeu (à noter que je ne suis pas forcément d'accord avec cette analyse, qui est liée en partie à la présence de mauvais complateur, plus qu'à la SL elle même, et comme dit qu'un certains nombre de points est pris en compte).
    - La taille du code el l'occupation mémoire (que je ne connais pas). Instancier un vector<char> et un vector<unsigned char>, par exemple, va créer deux jeux de fonctions. Peut-être que ça a un impact dans certains environnements très contraints, et que la facilité d'utilisation liée à la STL va faire que des programmateurs risquent de ne pas faire très attention à ce genre de choses.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  7. #27
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Merci pour la précision sur les strings
    C'est vrai que dans leur abstract, ils parlent surtout de choses qui concernent le compilo, mais la suite met fameusement du plomb dans l'aile de la stl.

    De plus, je trouve que cette EASTL apporte des choses intéressantes. Je n'ai pas eu le temps ni le courage de tout lire, mais ça s'annonce pas mal.
    Hélas il semblerait que ce soit loin d'être des sources disponibles

  8. #28
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Davidbrcz Voir le message
    Du pointeur de pointeur (de pointeur) c'est du bordel monstre en perspective.
    Imagine qu'un objet lance une exception lors de sa construction. Tu appercois le merdier pour désallouer ce qui l'a été ?
    J'ai trois questions, là... Je lis ce commentaire souvent (en fait à chaque fois que quelqu'un écrit un new), et je me pose les questions suivantes...

    1- dans quelles conditions (réaliste et sur une machine ayant moins de 20 ans) une ligne comme
    double *mat=new double[taille];
    peut envoyer une exception? J'avoue n'en avoir jamais vu, et ca fait déjà quelques années que je fais du C++... (et même sur des machines qui avaient bien moins de mémoire qu'aujourd'hui)...

    Ne nous protégeons nous pas là contre un risque inexistant ?

    2- si une telle exception était lancée, dans combien de cas la solution serait elle autre que la fermeture du programme (qui, mécaniquement, libère toute la mémoire allouée par le processus, et fait dispoaraitre les fuites mémoires)

    3- et quand bien même, est ce qu'une fuite mémoire sur un appel comme le précédent représente nécessairement un danger grave, à l'heure de la mémoire virtuelle et des Go?

    Attention, je comprends bien l'intérêt du RAII, je me demande simplement si la raison généralement invoquée, notamment dans ce cas précis de tableaux sur des structures natives, n'est pas une "terreur infantile", un héritage que nous avons du bon vieux mode 16 bit (que beaucoup n'ont pas connu), où un processus pouvait planter la machine, et où une allocation de mémoire pouvait planter sournoisement...

    Francois

  9. #29
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    1/ Deux types d'exceptions peuvent être lancées.
    std::bad_alloc et une exception perso.

    La première aura lieu si l'OS n'arrive pas à trouver assez de mémoire contiguë pour le tableau, c'est le genre de cas que je n'ai jamais rencontré, mais on doit pouvoir trouver des exemples sur le forum.

    Le second cas est beaucoup plus subtil. Imagine que chaque objet doit écrire quelque part (dans un fichier) ou se connecter au réseau ou what you whant.

    La construction d'un objet plante ( répertoire verouillé, réseau down) et il y a une exception. C'est ce genre de cas où ca va être la merde à gérer pour remettre le programme dans un état potable avec la moitié des objets aloués, l'autre pas et une erreur indépendante de notre programme.

    2/ C'est du cas par cas. L'exception peut être critique ou pas, chaque objet peut être vital pour le programme,.... Impossible de répondre: on peut devoir fermer le programme, attraper l'exception et continuer le programme, ...

    3/ Si tout le monde se dit ca, on est pas dans la merde (et c'est comme ca qu'on arrive à fabriquer Windows).

    Edit: Grilled par hiura
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  10. #30
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    1- Sur un PC qui avait juste 500Mo de RAM, j'ai déjà eu des disparitions régulières de FF et de chrome. La raison était une mémoire épuisée à causes des diverses autres applications qui tournaient (exceed, mauvais antivirus, java, FF, et xsltproc+fop sur le style docbook-xsl qui donnaient le coup de grâce à chaque fois)
    Un tel plantage fait tâche, en plus d'être pénible.

    Maintenant dans les diverses autres sources de problèmes : en général quand il y a une allocation dynamique, souvent la taille est aussi dynamique. Qui dit qu'elle est valide ? Que le fichier manipulé ou la trame socket reçue n'est pas corrompue ? Et oui, je l'ai déjà rencontré également.

    2- ben ... quand on cherche à manipuler une donnée corrompue que l'on ne maitrise pas, je ne vois pas pourquoi on devrait planter au lieu de dire "j'en veux pas. Suivant!"

    3- Ben ouais quand même. On n'a pas envie de voir un serveur critique au cœur d'un système qui repose sur lui planter à cause d'un interlocuteur qui envoie n'importe quoi.

    Programmer correctement ne coute rien. Surtout quand le résultat est plus facile à maintenir. Pourquoi ne pas le faire ?
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  11. #31
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par hiura Voir le message
    1) Si il n'y a pas de blocs mémoires contiguë assez grand.
    C'est exactement ce que je n'ai encore jamais vu se produire... En fait, même quand un programme utilise beaucoup de mémoire, elle n'est jamais allouée en un gros bloc contigu. C'est bien pour cela que je me pose la question de la réalité de ce problème.

    Citation Envoyé par hiura Voir le message
    2) Le problème c'est que tu ne peux pas dans toutes les applications te contenter de laisser planter bêtement le programme. Tu pourrais avoir certaines informations cruciales à sauvegarder.
    Je suis d'accord. Mais une exception non traitée ne veut pas dire un plantage sauvage. On pourrait parfaitement attraper l'exception et sauvegarder avant de sortir, ou avoir un gestionnaire d'erreur (type atexit(), qui fait les sauvegardes).

    Ce que je veux dire, c'est qu'il y a une grosse différence entre tolérer ce genre d'erreur exceptionnelle (quitte à les attrapper) et tolérer un plantage.

    Ceci dit, sauvegarder des infos cruciales à la sortie, et en faire dépendre le programme, c'est une folie. Car il suffit alors d'un bug pour avoir un plantage sale. Une application réelle doit pouvoir survivre à un plantage dégoutant, parce qu'on ne peut garantir un code sans bug.

    Citation Envoyé par hiura Voir le message
    3) Tu ne sais pas dans quel environnement l'application va être exécutée. Tu peux très bien avoir un client qui a un vieux PC, ou toute autre situation exotique.
    C'est vrai, mais pour manquer de mémoire à ce point, faut des machine très très anciennes, et sur celles là, il y a de grosses chances que rien ne marche... Une fois de plus, je pense que ces cas sont extrèmement rares, en général on connait à peu pres les machines sur lesquelles nos programmes s'exécuteront...

    Citation Envoyé par hiura Voir le message
    Et on ne sait pas : peut-être que dans quelques années les PC standard auront moins de mémoire et dédiront beaucoup au Cloud. A ce moment là, qqn qui voudra utiliser ton application ( en local ) sera bien embêtée et ne saura pas comment corriger l'erreur.
    Oui peut être, mais honnêtement, il me parait plus probable que la tendance actuelle, qui fait qu'on a de plus en plus de mémoire, des processeurs séparés pour des processus différents, continue...

    En fait, c'est une question assez générale en informatique. J'ai parfois l'impression qu'on passe beaucoup de temps à "refaire la dernière guerre". En gros, on parle beaucoup de portabilité (concept crucial à l'époque où il y avait presque autant d'OS que d'ordinateurs) au moment ou il n'y a presque plus qu'un OS vivant, on parle beaucoup de manque de mémoire à l'époque où on n'en manque plus, etc...

    Une fois de plus, je ne veux pas dire qu'il ne faut pas faire de RAII, juste que je ne suis pas convaincu par l'argument de l'exception.

    Francois

  12. #32
    Membre actif
    Étudiant
    Inscrit en
    Octobre 2007
    Messages
    189
    Détails du profil
    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2007
    Messages : 189
    Points : 213
    Points
    213
    Par défaut
    On peut toujours dire qu'on s'en fiche, ou croire que ça n'arrivera jamais car l'environnement de tests n'a rien révélé de particulier. Ou encore, en toute connaissance de cause, on peut dire qu'on s'en fiche, car ça ne dérange pas vraiment.

    Mais comme Davidbrcz l'a dit :
    Si tout le monde se dit ca, on est pas dans la merde (et c'est comme ca qu'on arrive à fabriquer Windows).
    Enfin, je crois que tout est résumé :
    Citation Envoyé par Luc Hermitte
    Programmer correctement ne coute rien. Surtout quand le résultat est plus facile à maintenir. Pourquoi ne pas le faire ?
    J'aurais même tendance à dire que ça peut mener à des économies importantes.

    ( Perso, je suis un peu fier d'avoir pondu un bon code plutôt qu'un ramassis de jenesaispasquoi, même si le résultat est strictement le même. )

  13. #33
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    1- Sur un PC qui avait juste 500Mo de RAM, j'ai déjà eu des disparitions régulières de FF et de chrome. La raison était une mémoire épuisée à causes des diverses autres applications qui tournaient
    Es tu bien certain qu'il s'agisse de bad_alloc??? Et dans des cas d'allocation de tableaux de types natifs??? En général, une forte utilisation de mémoire (sur les systèmes modernes, la mémoire n'est presque jamais épuisée) a tendance à faire apparaitre tous les bugs d'un programme...

    Citation Envoyé par Luc Hermitte Voir le message
    Maintenant dans les diverses autres sources de problèmes : en général quand il y a une allocation dynamique, souvent la taille est aussi dynamique. Qui dit qu'elle est valide ? Que le fichier manipulé ou la trame socket reçue n'est pas corrompue ? Et oui, je l'ai déjà rencontré également.
    Là je suis bien d'accord, mais note que la STL n'est pas du tout immunisée contre ce genre de malheur : l'index sur ton vector renvoyé n'est pas le bon, tant pis pour toi... Ou alors il faut ajouter des tests pour chaque conteneur, ce qui ne donne un code ni élégant, ni efficace...

    Il me semble que c'est typiquement là qu'une boucle try/catch est utile... Encore que, personnellement, je préfère un test.

    Citation Envoyé par Luc Hermitte Voir le message
    2- ben ... quand on cherche à manipuler une donnée corrompue que l'on ne maitrise pas, je ne vois pas pourquoi on devrait planter au lieu de dire "j'en veux pas. Suivant!"
    Il me semble que si tu es dans une situation ou une allocation de tableau de types natifs (de taille raisonnable) peut échouer, espérer un fonctionnement correct du programme est espérer beaucoup. Mais cela tient sans doute au fait que je n'ai jamais vu de bad_alloc... En fait, la première fois que j'en verrai un, cela méritera non seulement d'arrêter le programme, mais aussi d'envoyer à l'utilisateur un message de félicitations, et peut etre un avoir sur ses achats futurs...

    Citation Envoyé par Luc Hermitte Voir le message
    Programmer correctement ne coute rien. Surtout quand le résultat est plus facile à maintenir. Pourquoi ne pas le faire ?
    Qui peut en disconvenir?

    J'essaie juste de comprendre en quoi les "new" sont dangereux... Et je dois dire que l'explication par les exceptions ne me parait pas satisfaisante.

    Francois
    Dernière modification par Invité ; 31/05/2009 à 19h12.

  14. #34
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Davidbrcz Voir le message
    1/ Deux types d'exceptions peuvent être lancées.
    std::bad_alloc et une exception perso.
    Comment peux tu avoir une exception perso dans une allocation de types natifs???

    Citation Envoyé par Davidbrcz Voir le message
    3/ Si tout le monde se dit ca, on est pas dans la merde (et c'est comme ca qu'on arrive à fabriquer Windows).
    Je ne comprend pas... Dans tous les OS actuels, chaque processus gère son espace d'adressage propre, non... Donc, une fuite mémoire ne concerne que ce processus, non?

    Alors, si les cas de bad_alloc sont extrèmement rares, s'ils ne concernent pas directement les autres processus, en quoi est on dans la merde?

    En 16 bits, sous DOS, sous les premier windows (3.1 et les autres), bien sur, c'était tout autre chose... Mais sur XP?

    Francois

  15. #35
    Membre actif
    Étudiant
    Inscrit en
    Octobre 2007
    Messages
    189
    Détails du profil
    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2007
    Messages : 189
    Points : 213
    Points
    213
    Par défaut
    Citation Envoyé par fcharton Voir le message
    Comment peux tu avoir une exception perso dans une allocation de types natifs???
    Soit une classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class QuiPlante {
    public : QuiPlante(void) { throw whatyouwant(); }
    };
    Bien sûr c'est un exemple bidon, mais voilà une situation ou ce n'est pas l'allocation de la mémoire qui ne va pas, mais la construction de l'objet.


    Citation Envoyé par fcharton Voir le message
    Je ne comprend pas... Dans tous les OS actuels, chaque processus gère son espace d'adressage propre, non... Donc, une fuite mémoire ne concerne que ce processus, non?
    Ce n'est pas un problème de fuite de mémoire, mais prend l'exemple suivant.

    Tu utilises un logiciel de dessin qui doit faire des allocations sans les contrôler. Tu seras bien déçu quand l'application va planter sans sauver ton projet.

  16. #36
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Citation Envoyé par hiura Voir le message
    Soit une classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class QuiPlante {
    public : QuiPlante(void) { throw whatyouwant(); }
    };
    Bien sûr c'est un exemple bidon, mais voilà une situation ou ce n'est pas l'allocation de la mémoire qui ne va pas, mais la construction de l'objet.
    Il parlait de classe NATIVE.

  17. #37
    Membre actif
    Étudiant
    Inscrit en
    Octobre 2007
    Messages
    189
    Détails du profil
    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2007
    Messages : 189
    Points : 213
    Points
    213
    Par défaut
    Haa... Mais... Je connais les types natifs, mais les _class_ natives pas. Kesako ?

  18. #38
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par hiura Voir le message
    Soit une classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class QuiPlante {
    public : QuiPlante(void) { throw whatyouwant(); }
    };
    Bien sûr c'est un exemple bidon, mais voilà une situation ou ce n'est pas l'allocation de la mémoire qui ne va pas, mais la construction de l'objet.
    Ce n'est pas bidon du tout, et c'est une excellent raison d'utiliser des conteneurs sécurisés ou à tout le moins de mettre ses new dans des clauses try, quand on utilise des types définis par l'utilisateur (class ou struct).

    Ma question, depuis le début, porte sur les types natifs, les int, les doubles, etc...

    Citation Envoyé par hiura Voir le message
    Ce n'est pas un problème de fuite de mémoire, mais prend l'exemple suivant.

    Tu utilises un logiciel de dessin qui doit faire des allocations sans les contrôler. Tu seras bien déçu quand l'application va planter sans sauver ton projet.
    Oui, mais tu seras aussi déçu si tu as bien controlé tes allocations mais si un autre bug te fait planter sans sauver le projet. Le problème, ici, est dans la conception.

    Ne sauvegarder le travail de l'utilisateur qu'à la sortie du programme, et pas en cours de route, c'est s'exposer à la catastrophe en cas de plantage... Donc, à moins que tu sois un extra terrestre qui programme sans bug, il est indispensable de ne pas utiliser un tel schéma, mais de faire, à l'insu de l'utilisateur, des sauvegardes de son travail, et de pouvoir les lui rendre (comme dossiers récupérés) après redémarrage, en cas de plantage. Chez Microsoft, Word fait cela remarquablement bien.

    Francois
    Dernière modification par Invité ; 31/05/2009 à 21h46.

  19. #39
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Citation Envoyé par hiura Voir le message
    Haa... Mais... Je connais les types natifs, mais les _class_ natives pas. Kesako ?
    OK, j'ai dit classes, mea culpa. fcharton a bien parlé de types.

  20. #40
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Bah sur les types natifs, j'ai envie de dire qu'il suffit de faire de le calcul.

    On peut dire qu'a 600 Mo contiguës (ca me parait réaliste, surotut sous window, ca lance une exception, donc ca fait :
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

Discussions similaires

  1. Forum des bonnes pratiques en gestion de projet 2014
    Par QRP-France dans le forum Communiqués
    Réponses: 0
    Dernier message: 20/08/2014, 17h58
  2. Des bonnes pratiques et toujours des questions
    Par dafpp dans le forum Débuter
    Réponses: 29
    Dernier message: 04/12/2013, 00h26
  3. question a propos des bonnes pratiques ACCESS
    Par amne26 dans le forum IHM
    Réponses: 1
    Dernier message: 25/09/2008, 18h52
  4. [XML] Synthèse des bonnes pratiques XML
    Par neuromencien dans le forum XML/XSL et SOAP
    Réponses: 2
    Dernier message: 21/03/2007, 21h55
  5. De la bonne pratique des includes...
    Par say dans le forum C++Builder
    Réponses: 4
    Dernier message: 24/11/2005, 11h15

Partager

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