opérateurs New et Delete

12 réponses
Avatar
MGN
Bonjour,
étant potentiellement confronté à un problème de mémoire insuffisante en cas
d'utilisation des opérateurs new et delete,
j'ai dans l'idée de redéfinir des opérateurs New et Delete (implémentés
comme fonctions membres static pour certaines classes), qui seraient
attachés à des blocs de mémoire éventuellement réservés sur le disque (en
dernier recours).
(nota : je préfère ne pas redéfinir les opérateurs new et delete => à moi de
faire attention)
Avez-vous déjà fait cela et si oui, avez-vous des liens vers des exemples ?
Merci à vous.
Marc

10 réponses

1 2
Avatar
Jean-Marc Bourguet
"MGN" writes:

Bonjour,
étant potentiellement confronté à un problème de mémoire insuffisante en
cas d'utilisation des opérateurs new et delete,
j'ai dans l'idée de redéfinir des opérateurs New et Delete (implémentés
comme fonctions membres static pour certaines classes), qui seraient
attachés à des blocs de mémoire éventuellement réservés sur le disque (en
dernier recours).
(nota : je préfère ne pas redéfinir les opérateurs new et delete => à moi
de faire attention)
Avez-vous déjà fait cela et si oui, avez-vous des liens vers des exemples ?
Merci à vous.



Tu ne peux pas definir d'operateurs autres que ceux prevus par le langage.


Je suppose que tu veux faire des fonctions qui renvoient un proxy
(vraisembablement ayant un operator-> en plus pour la facilite
d'utilisation). A chaque acces, le proxy verifie si l'objet est reellement
en memoire ou pas, auquel cas il le charge.

Il va te falloir un deuxieme niveau d'indirection pour etre notifie de la
fin des expressions (et eviter que dans des expressions complexes, tu ne
recuperes de la memoire en cours d'utilisation).


En passant, avec le controle sur l'overcommit qui est global pour le
systeme plutot que local a chaque application, c'est difficile d'etre sur
qu'une allocation a reussit meme si elle renvoie qqch de non nul.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Michael Doubez
On 2 mar, 13:44, Jean-Marc Bourguet wrote:
"MGN" writes:
> Bonjour,
> tant potentiellement confront un probl me de m moire insuffisante en
> cas d'utilisation des op rateurs new et delete,
> j'ai dans l'id e de red finir des op rateurs New et Delete (impl ment s
> comme fonctions membres static pour certaines classes),  qui seraient
> attach s des blocs de m moire ventuellement r serv s sur le disque (en
> dernier recours).
> (nota : je pr f re ne pas red finir les op rateurs new et delete => m oi
> de faire attention)



C'est vous qui voyez. Y'en a qu'ont essayé :)

> Avez-vous d j fait cela et si oui,  avez-vous des liens vers des exem ples ?



"Modern C++ etc." par Andrei Alexandrescu pour la surcharche des
operateurs (si tu changes d'avis) et pour des exemples d'allocateurs
par block ...


Tu ne peux pas definir d'operateurs autres que ceux prevus par le langage .

Je suppose que tu veux faire des fonctions qui renvoient un proxy
(vraisembablement ayant un operator-> en plus pour la facilite
d'utilisation).  A chaque acces, le proxy verifie si l'objet est reelle ment
en memoire ou pas, auquel cas il le charge.



Je n'ai pas compris ça. J'ai supposé qu'il voualit allouer de la
mémoire dans une mmap() par exemple.

[snip]

--
Michael
Avatar
Fabien LE LEZ
On Tue, 2 Mar 2010 13:28:08 +0100, "MGN" :

étant potentiellement confronté à un problème de mémoire insuffisante



Pourrais-tu en dire plus ?
Avatar
MGN
>>étant potentiellement confronté à un problème de mémoire insuffisante


Pourrais-tu en dire plus ?



oui bien sûr et je réalise que si la question n'est pas claire c'est que le
problème n'est pas clair dans ma tête (ou plutôt bien compliqué pour moi à
ce stade).
Pour simplifier :
j'ai des "petites" classes dérivées d'une classe de base CObject avec des
opérateurs redéfinis.
Par exemple CObject + CObject retourne un pointeur CObject* alloué dans le
tas avec new.
Jusque là, pas de problème.
J'ai aussi défini de "gros" objets qui contiennent un vector<CObject*> (il
s'agit de champs de table pour fixer les idées), où la mémoire associée aux
objets de base est allouée dans le tas. Evidement, si la taille du champ
augmente, je peux avoir des problèmes de mémoire insuffisante. De plus il
peut y avoir des opérations entre champs, etc..
D'où mon idée (actuellement au stade conceptuel) :
définir un "opérateur" personnel New (avec l'"opérateur" Delete associé) qui
retournerait non pas une adresse mémoire valide mais un décalage dans une
plage. Cette plage serait "matérialisée" par une classe CMemory par exemple
(et utilisation du modèle singleton sans doute), capable de retrouver le
contenu d'un objet à partir de la valeur du décalage. Cette classe CMemory
pourrait le cas échéant lire la valeur à partir d'un fichier (et plus
généralement gérer les ressources mémoire réelles).
D'une manière générale, j'aimerais bien séparer les problèmes et ne pas
avoir à "gérer" les insuffisances de mémoire éventuelles dans ma hiérarchie
de classes dérivées de CObject.
A ce stade, je pressens que le plus gros problème si j'adopte cette solution
sera la gestion de la fragmentation et la libération de cette mémoire
"virtuelle".
Est-ce que vous avez connaissance d'une classe qui ferait ceci (l'équivalent
de la classe CMemory ci-dessus décrite)?
ps : j'ai aussi lu que l'allocation de petits objets avec new n'était pas
optimale
http://www.ensta.fr/~enstar/doc/c++/courscpp/Sections/Sect07-B9.html
d'où l'intérêt possible pour moi d'une telle classe, d'autant que j'ai déjà
pour tous mes objets des fonctions de lecture/écriture efficaces.
J'espère avoir été plus clair.
Marc
Avatar
Fabien LE LEZ
On Tue, 2 Mar 2010 22:36:55 +0100, "MGN" :

A ce stade, je pressens que le plus gros problème si j'adopte cette solution
sera la gestion de la fragmentation et la libération de cette mémoire
"virtuelle".



J'ai surtout l'impression que tu essaies de recréer à la main le
système de mémoire virtuelle qui existe déjà dans les OS modernes.

Evidement, si la taille du champ
augmente, je peux avoir des problèmes de mémoire insuffisante.



Un des trucs fondamentaux que j'ai appris en cours de maths : toute
proposition précédée du mot "évidemment" est probablement fausse.

Il faudrait que tu donnes plus de contexte : comptes-tu avoir besoin
d'adresser plus de 2 Go de mémoire, tout en restant en 32 bits ?
[Je parle bien de "mémoire" en général -- sa localisation
(RAM physique ou swap) n'est pas un paramètre auquel tu as accès.]

Si la réponse est "non", tu cherches des complications pour rien.

Si la réponse est "oui", pose-toi à nouveau la question. Le 32 bits
disparaît, lentement mais sûrement.

lire la valeur à partir d'un fichier



Peux-tu confirmer que tu as bien compris le contenu de cette page ?
http://varnish-cache.org/wiki/ArchitectNotes
Avatar
MGN
> J'ai surtout l'impression que tu essaies de recréer à la main le
système de mémoire virtuelle qui existe déjà dans les OS modernes.



oui, ça revient à ça...
j'avoue que je ne suis pas très à l'aise avec la mémoire quand elle
manque...
(je suis autodidacte en informatique et j'ai commencé directement avec le
C++, donc avec l'opérateur new :-), sans me prendre trop la tête avec ces
problèmes)

Il faudrait que tu donnes plus de contexte : comptes-tu avoir besoin
d'adresser plus de 2 Go de mémoire, tout en restant en 32 bits ?
[Je parle bien de "mémoire" en général -- sa localisation
(RAM physique ou swap) n'est pas un paramètre auquel tu as accès.]

Si la réponse est "non", tu cherches des complications pour rien.



a priori je pensais en effet ne pas avoir besoin d'autant de mémoire (au
doigt mouillé, vu la taille sur disque d'un fichier de données écrites par
mon programme)
Actuellement mon exe fait 11 Mo, il me reste donc de la marge pour les
données....
Je suis sous Vista 64bits avec 8 Go de RAM.
Mais comme j'utilise BCB 2007 32 bits, je suppose que seuls 4 Go sont
adressables (moins 2Go pour le système & co, au pire, ça reste a priori
important quand même !).

J'ai eu un message "mémoire insuffisante" alors que je réalisais des
traitements sur une table de 400 000 enregistrements et 80 variables...
Je pensais que les problèmes surgiraient pour des tables plus volumineuses,
qui ne sont pas la cible de mon programme. Mon programme est en fait un
compilateur (Bytecode immédiatement "exécuté", je ne connais pas le terme
exact) d'un langage de traitement statistique et je suis certain de ne pas
avoir de fuite de mémoire (testé / contrôlé et archi-contrôlé à tous les
niveaux !).

Si la réponse est "oui", pose-toi à nouveau la question. Le 32 bits
disparaît, lentement mais sûrement.



oui, c'est vraiment là dessus que je compte... !


Peux-tu confirmer que tu as bien compris le contenu de cette page ?
http://varnish-cache.org/wiki/ArchitectNotes



If all this sounds foreign to you, ...
Désolé, c'est un peu technique pour moi (et je précise que mon programme
n'utilise pas le multithread à ce jour)
Je fais de nombreux appels à new pour de petits objets. Je sais que ce n'est
pas ce qu'il y a de plus performant...mais de là à "saturer" la mémoire ?
Que penses-tu de la redéfinition de new proposée ci-après ?
http://www.ensta.fr/~enstar/doc/c++/courscpp/Sections/Sect07-B9.html
Merci pour ta réponse.
Avatar
Fabien LE LEZ
On Wed, 3 Mar 2010 01:03:51 +0100, "MGN" :

(je suis autodidacte en informatique et j'ai commencé directement avec le
C++,



donc avec l'opérateur new



Euh... bof. Dans tout ce que j'ai programmé en C++, l'utilisation de
new est plutôt rare -- je préfère allouer les objets sur la pile.
(Et, bien sûr, je n'utilise jamais delete directement, ou quasiment
jamais.)

YMMV.

Je suis sous Vista 64bits avec 8 Go de RAM.
Mais comme j'utilise BCB 2007 32 bits,



Essaie Visual C++. C'est gratuit, et ils ont fait énormément de
progrès ces dernières années.

J'ai eu un message "mémoire insuffisante"



D'où ce message venait-il ? Es-tu sûr de l'avoir recopié intégralement
et sans erreur ?

Peux-tu confirmer que tu as bien compris le contenu de cette page ?
http://varnish-cache.org/wiki/ArchitectNotes



If all this sounds foreign to you, ...



Au pire, ne lis pas jusque là.

J'ai bien peur que tu essaies de faire ce qu'il appelle "1975
programming", c'est-à-dire refaire, en moins bien, ce que les OS
récents (> 1990) font déjà.

Désolé, c'est un peu technique pour moi



Si le contenu de cette page te dépasse, oublie ton idée de départ.

Je fais de nombreux appels à new pour de petits objets.



Perso, si j'ai beaucoup de petits objets, je les mets tous dans un
vector<>, qui s'occupe d'allouer un bloc contigu, donc une seule
allocation, et pas de fragmentation.
Avatar
Fabien LE LEZ
On Wed, 3 Mar 2010 01:03:51 +0100, "MGN" :

Je sais que ce n'est
pas ce qu'il y a de plus performant...



N'essaie pas trop de prévoir où se situeront les problèmes de
performance. Un profiler le fera bien mieux que toi.
Avatar
MGN
mes excuses à Fabien LE LEZ ... j'ai cliqué sur Répondre (à l'expéditeur
donc) et pas sur Répondre au groupe
=> je reposte

Euh... bof. Dans tout ce que j'ai programmé en C++, l'utilisation de
new est plutôt rare -- je préfère allouer les objets sur la pile.
(Et, bien sûr, je n'utilise jamais delete directement, ou quasiment
jamais.)



ben moi de même, mais quand j'alloue de la mémoire, j'utilise new et pas
malloc...pas toi ?

Désolé, c'est un peu technique pour moi



Si le contenu de cette page te dépasse, oublie ton idée de départ.



quand je ne sais pas, j'apprends !

Je fais de nombreux appels à new pour de petits objets.



Perso, si j'ai beaucoup de petits objets, je les mets tous dans un
vector<>, qui s'occupe d'allouer un bloc contigu, donc une seule
allocation, et pas de fragmentation.



oui, mais on n'a pas toujours le choix. Je te rassure, je ne fais jamais un
vector<int*>. Mais la fragmentation elle est bien souvent là quand même (ex:
vector<std::string>).
Dans mon cas, il se trouve que je n'ai pas le choix...

merci pour tes encouragements :-(
Avatar
Fabien LE LEZ
On Wed, 3 Mar 2010 12:03:09 +0100, "MGN" :

ben moi de même, mais quand j'alloue de la mémoire, j'utilise new et pas
malloc...pas toi ?



Non. Quand j'ai besoin d'un bloc "brut" de mémoire, j'utilise
std::vector<char>.

new commence à être utile quand un objet à sémantique d'identité doit
avoir une longue durée de vie, ou bien quand on doit stocker/gérer des
pointeurs vers une classe de base (et utiliser le polymorphisme
dynamique). C'est fréquent, mais c'est loin d'être la majorité des
objets.

(Évidemment, on se sert aussi de new quand on veut réimplémenter la
STL. Mais je n'ai pas le niveau pour faire ça en production.)

Si le contenu de cette page te dépasse, oublie ton idée de départ.



quand je ne sais pas, j'apprends !



OK, je modifie donc ma phrase : Tant que le contenu de cette page te
dépasse, n'implémente pas ton idée de départ.

Ou, dit autrement : si tu veux remplacer la système de mémoire
virtuelle des OS modernes, assure-toi d'abord que tu le comprends
bien.


[Note : si je n'ai pas répondu à ta question d'origine sur
l'implémentation en C++, c'est parce que je n'ai rien à rajouter aux
réponses de Jean-Marc et Michael.]
1 2