Bonjour,
Je souhaiterais pouvoir interdire l'utilisation de l'opérateur new à partir d'un certain moment dans mon code. Du coup, je me dis que de le redéfinir est la solution. Mais je ne vois pas comment.
Cordialement,
Julien.
Version imprimable
Bonjour,
Je souhaiterais pouvoir interdire l'utilisation de l'opérateur new à partir d'un certain moment dans mon code. Du coup, je me dis que de le redéfinir est la solution. Mais je ne vois pas comment.
Cordialement,
Julien.
Bonjour,
A ta place, je passerais par une factory générique (enfin, en réalité à ta place, je réfléchirai 2 ou 3 fois de plus à savoir pourquoi je veux faire cette opération des plus étranges et voir ce qui peut être fait de bien plus belle manière à cette fin).
Par contre je laisse de côté les paramètres du constructeur (sûrement très simple à ajouter en C++11, moins sans ça je trouve).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 class Factory { template<class T> static bool New(T*& t) { t = NULL; if (canConstruct()) { t = new T; return true; } return false; } template<class T> static bool NewArray(T*& t, unsigned int size) { t = NULL; if (canConstruct()) { t = new T[size]; return true; } return false; } // return false pour interdire la construction static bool canConstruct() { return true; } }; int* array; if (Factory::NewArray(array, 10)) { // manipulation de mon array[10] correctement créé delete[] array; }
Du coup je m'interdis aussi les déclarations sans pointeur.
Merci pour vos réponses.
Alors l'intérêt d'interdire une allocation mémoire dynamique est du au fait que l'on est dans un contexte de système embarqué. Il y a donc une étape de configuration au démarrage pendant laquelle les allocations sont autorisées, puis interdites par la suite (d'ou le "à partir d'un moment").
Julien.
Là, c'est une autre paire de manche.
Il s'agit d'interdire toute allocation dynamique, pas seulement celles de quelques classes.
Le mieux, c'est de spécifier ce comportement, et de taper sur tout développeur qui ne s'y soumet pas :aie:
Oui voila, la difficulté est qu'il faut vraiment interdire tout type d'allocation dynamique. Je t'avouerai que j'avais pensé à ta solution =). Après bon effectivement sur des "petits" projets un simple mot peut suffire, mais pour de la programmation multi-sites (France, Angleterre, Chine, ...) il y aura toujours quelqu'un qui ne respectera pas cette règle :(
Julien.
Une spécification est un "commandement divin devant absolument être suivi sous peine de rejet du projet par le client". Spécifier, c'est donner un ordre qui ne peut pas être refusé.
Cela dit, l'interdiction posée bloque aussi l'utilisation des string, des collections, et des lazy-singletons et j'en passe.
Dans ce cas, tu peux tricher violemment, en imposant une redéfinition à la compilation de malloc et new via une macro. Je pense à -Dnew="null;exit(-1);//" ou -Dnew="null;throw 0;//" (ou la variante #define en forçant l'inclusion du .h le contenant par la spec)
Mais c'est probablement trop violent.
Mais si le problème est la taille mémoire, un gros paquets de variable aura le même effet qu'un new: l'encombrement.
Du coup, pour quelle raison veux-tu interdire totalement l'allocation dynamique?
Le système en cours de programmation NE devra JAMAIS rebooter et devra rester en marche des mois voire des années. De plus, pendant cette période, il communiquera avec d'autres systèmes, et des données seront transférées toutes les X ms. Du coup, si une allocation mémoire échoue (ce qui peut arriver) à un moment M, il y a un risque de pertes de données. De plus, nous ne sommes pas limités en espace mémoire. Donc l'utilisation de taille fixe ne nous pose pas de problèmes.
En gros, le système a le droit de "planter" pendant la phase de configuration mais pas après.
Il faut déjà commencer par être clair avec toi même.
Tu veux interdire new après la phase de configuration. Certes. Cela veut il dire que tu ne pourra plus utiliser de std::vector Tous tes tableaux devront être de taille fixe dès le début ? Pas de std::string ? ...
Car si tu veux interdire tous les new que les utilisateurs peuvent écrire, suffit d'une macro dans ce genre
C'est certes degeulasse, mais efficace.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 #include <iostream> #include <vector> using namespace std; template<int> struct CompileTimeError; template<> struct CompileTimeError<true> {}; #define static_check(expr, msg) \ { CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; } #define new static_check(0,_NEW_NOT_ALLOWED) int main(void) { std::vector<int> foo; foo.push_back(5); std::cout<<foo.size()<<std::endl; // int* p=new int; //retire le commentaire et ca plante int i=5; ++i; std::cout<<i<<" "<<foo[0]<<std::endl; }
Si quelqu'un a une solution moins crade, je suis preneur (surcharge propre de new ?).
je suis pas sur que ca doit etre fait at runtime.
tu devrais plutot localiser ta conf/load dans un dossier, et faire un bon vieux grep sur les autres dossiers (mettant en jeux le fonctionnement normal (la phase running))
edit: pas vu message de 13h06, mais l'idee est la meme
N'utilisez-vous pas de review de code où vous pouvez définir des règles comme interdire l'opérateur new ?
Par contre comme les autres, je trouve ça léger comme règle pour s'assurer que la mémoire ira bien. Rien n'interdira de créer un tableau statique qui fasse exploser la mémoire après tout.
Et finalement, dynamique ou statique c'est surtout une question de portée des données : doivent-elles subsister ou non en dehors du scope de leur déclaration ?
Mais dans l'absolu, c'est très similaire.
Bonjour,
Tu peux te faire un allocateur perso, tu réserves un plage de données au début et après tu tapes dedans à chaque fois. Par contre il faudra pas oublie de l'utiliser (spécifer le paramètre optionnel des conteneurs par exemple). Pour l'implémentation, recherche sur internet des articles détaillant la mise en place d'allocateur pour les petits objets, le raisonnement est assez proche (sauf que les objets sont pas petits et que la zone aura une taille fixe).
Par contre je suis assez sceptique quand au réel interêt, tu ne peux vraiment pas faire confiance au système ? Quel est la probabilité qu'une allocation échoue (sachant que ca ne peut pas être à cause d'un manque de mémoire comme tu le sous-entend) ?
Oui effectivement, cela ouvre une autre question à laquelle je n'ai pas la réponse: quel est la probabilité d'une erreur d'allocation mémoire ? D'ailleurs, une allocation mémoire échoue t-elle seulement en cas de mémoire insuffisante ?
Enfin bon faudra que je me documente sur ce point ^^.
Merci à vos réponses, c'est toujours intéressant d'avoir des critiques sur des méthodes de programmation.
Julien.
Mieux vaut avoir des allocations surveillées (catch des exceptions, controles des retours) plutot que de les interdires.
J'imagine mal quelqu'un dire: "Voici une voiture, je vous mets deux litres d'essences, rendez-vous à l'autre bout du monde. Oh! J'oubliais, j'ai soudé le bouchon du réservoir..."