Je programme en VC6++, mais j'ai encore certaines "lacunes" en
programmation.
J'aimerais notamment avoir des exemples de structures de donnees de type
pile ou file, qui me permettrait une gestion un peu plus dynamique de la
memoire, notamment au stade ou j'en suis je cree des tableaux de 100
"cases" alors qu'en general je n'en utilise qu'une dizaine de celles-ci.
Si vous aviez un site simple ou je pourrais trouver ca ce serait cool.
un exemple, parmis tant d'autres... c'est pas mon preferé, mais c'est tout ce que j'ai sous la main. je prefere la version template non membre, genre template<class T> T * operator new(T *objet,size_t count) ; (ou count,objet, je sais plus...)
class Point { private : int x,y; Point *next; static Point *freeP; static const int packNb; public : ... void* operator new(size_t); void operator delete(void *); };
void* Point::operator new(size_t sz) { Point *p; if (!freeP) { size_t packSz = packNb*sz; // Alloc. espace pr packNb Points freeP = (Point *)new char[packSz]; for (int i=1,p=freeP;i<packNb;i++,p++) p->next = p+1;// Mise en liste p->next = 0; } p=freeP; freeP=freeP->next; return p; } void Point::operator delete(void* pt) { ((Point*)pt)->next = freeP; freeP = (Point*)pt; }
Point* Point::freeP=0; const int packNbP; Point* p = new Point(3,4); // Point::new(sizeof(Point)) // puis Point::Point(3,4)
un exemple, parmis tant d'autres... c'est pas mon preferé, mais c'est tout
ce que j'ai sous la main. je prefere la version template non membre, genre
template<class T> T * operator new(T *objet,size_t count) ; (ou count,objet,
je sais plus...)
class Point
{
private :
int x,y;
Point *next;
static Point *freeP;
static const int packNb;
public :
...
void* operator new(size_t);
void operator delete(void *);
};
void* Point::operator new(size_t sz) {
Point *p;
if (!freeP)
{
size_t packSz = packNb*sz;
// Alloc. espace pr packNb Points
freeP = (Point *)new char[packSz];
for (int i=1,p=freeP;i<packNb;i++,p++)
p->next = p+1;// Mise en liste
p->next = 0;
}
p=freeP; freeP=freeP->next;
return p;
}
void Point::operator delete(void* pt) {
((Point*)pt)->next = freeP;
freeP = (Point*)pt;
}
Point* Point::freeP=0;
const int packNbP;
Point* p = new Point(3,4);
// Point::new(sizeof(Point))
// puis Point::Point(3,4)
un exemple, parmis tant d'autres... c'est pas mon preferé, mais c'est tout ce que j'ai sous la main. je prefere la version template non membre, genre template<class T> T * operator new(T *objet,size_t count) ; (ou count,objet, je sais plus...)
class Point { private : int x,y; Point *next; static Point *freeP; static const int packNb; public : ... void* operator new(size_t); void operator delete(void *); };
void* Point::operator new(size_t sz) { Point *p; if (!freeP) { size_t packSz = packNb*sz; // Alloc. espace pr packNb Points freeP = (Point *)new char[packSz]; for (int i=1,p=freeP;i<packNb;i++,p++) p->next = p+1;// Mise en liste p->next = 0; } p=freeP; freeP=freeP->next; return p; } void Point::operator delete(void* pt) { ((Point*)pt)->next = freeP; freeP = (Point*)pt; }
Point* Point::freeP=0; const int packNbP; Point* p = new Point(3,4); // Point::new(sizeof(Point)) // puis Point::Point(3,4)
adebaene
"Manuel Leclerc" wrote in message news:<40333374$...
Arnaud Debaene a écrit :
> - Pour créer un objet dans une zone mémoire > particulière, comme un memory mapped file pour > partager un objet entre plusieurs processus.
Jésus Marie Joseph,
Tu peux aussi rajouter Allah et Bouddha avec ce genre de bricolages!!
on peut vraiment faire une chose pareille ?
Et oui! ;-)
Et le code, il est où ?
Il faut qu'il soit dans chacun des programmes (compilés avec exactement le même compilateur et les mêmes options de compilation pour être sûr - une DLL peut être une bonne idée).
Le vrai problème en fait avec cette technique, c'est le v-ptr, qui pointe vers la v-table dans l'un des processus et n'importe où dans l'autre (il n'y a aucune raison que les v-tables d'un type soient au même endroit dans 2 processus séparés). En clair c'est utilisable (avec des pincettes) uniquement pour les PODs qui ne contiennent ni pointeurs ni référence.
J'ai entendu des projets qui consisteraient à utiliser des pointeurs "relatifs" par rapport à l'adresse de mapping du MMF au lieu de pointeurs absolus pour pouvoir utiliser des structures avec pointeur, mais je ne l'ai encore jamais vu mis en oeuvre.
C'est par ailleurs à proscrire absolument si tu n'est pas maître de tous les softs qui accèdent à l'objet : le risque d'incompatibilité binaire est trop important.
Arnaud
"Manuel Leclerc" <manuel.leclerc@alussinan.org> wrote in message news:<40333374$1@neottia.net>...
Arnaud Debaene a écrit :
> - Pour créer un objet dans une zone mémoire
> particulière, comme un memory mapped file pour
> partager un objet entre plusieurs processus.
Jésus Marie Joseph,
Tu peux aussi rajouter Allah et Bouddha avec ce genre de bricolages!!
on peut vraiment faire une
chose pareille ?
Et oui! ;-)
Et le code, il est où ?
Il faut qu'il soit dans chacun des programmes (compilés avec
exactement le même compilateur et les mêmes options de compilation
pour être sûr - une DLL peut être une bonne idée).
Le vrai problème en fait avec cette technique, c'est le v-ptr, qui
pointe vers la v-table dans l'un des processus et n'importe où dans
l'autre (il n'y a aucune raison que les v-tables d'un type soient au
même endroit dans 2 processus séparés). En clair c'est utilisable
(avec des pincettes) uniquement pour les PODs qui ne contiennent ni
pointeurs ni référence.
J'ai entendu des projets qui consisteraient à utiliser des pointeurs
"relatifs" par rapport à l'adresse de mapping du MMF au lieu de
pointeurs absolus pour pouvoir utiliser des structures avec pointeur,
mais je ne l'ai encore jamais vu mis en oeuvre.
C'est par ailleurs à proscrire absolument si tu n'est pas maître de
tous les softs qui accèdent à l'objet : le risque d'incompatibilité
binaire est trop important.
"Manuel Leclerc" wrote in message news:<40333374$...
Arnaud Debaene a écrit :
> - Pour créer un objet dans une zone mémoire > particulière, comme un memory mapped file pour > partager un objet entre plusieurs processus.
Jésus Marie Joseph,
Tu peux aussi rajouter Allah et Bouddha avec ce genre de bricolages!!
on peut vraiment faire une chose pareille ?
Et oui! ;-)
Et le code, il est où ?
Il faut qu'il soit dans chacun des programmes (compilés avec exactement le même compilateur et les mêmes options de compilation pour être sûr - une DLL peut être une bonne idée).
Le vrai problème en fait avec cette technique, c'est le v-ptr, qui pointe vers la v-table dans l'un des processus et n'importe où dans l'autre (il n'y a aucune raison que les v-tables d'un type soient au même endroit dans 2 processus séparés). En clair c'est utilisable (avec des pincettes) uniquement pour les PODs qui ne contiennent ni pointeurs ni référence.
J'ai entendu des projets qui consisteraient à utiliser des pointeurs "relatifs" par rapport à l'adresse de mapping du MMF au lieu de pointeurs absolus pour pouvoir utiliser des structures avec pointeur, mais je ne l'ai encore jamais vu mis en oeuvre.
C'est par ailleurs à proscrire absolument si tu n'est pas maître de tous les softs qui accèdent à l'objet : le risque d'incompatibilité binaire est trop important.
Arnaud
Manuel Leclerc
Arnaud Debaene a écrit :
Manuel Leclerc wrote ...
> on peut vraiment faire une > chose pareille ?
Et oui! ;-)
> Et le code, il est où ?
Il faut qu'il soit dans chacun des programmes (compilés avec exactement le même compilateur et les mêmes options de compilation pour être sûr - une DLL peut être une bonne idée).
[...]
o_O
Et chargée à la même adresse, la DLL, non ?
Bon sérieux, ça existe dans la vraie vie un truc pareil ? Pas taper, je demande.
Ca m'a l'air quand même un poil plus simple de faire de simples structures de données, avec des offsets au lieu de pointeurs si nécessaires, puis de les encapsuler par des vrais objets dans chaque process, non ?
Arnaud Debaene a écrit :
Manuel Leclerc wrote ...
> on peut vraiment faire une
> chose pareille ?
Et oui! ;-)
> Et le code, il est où ?
Il faut qu'il soit dans chacun des programmes (compilés
avec exactement le même compilateur et les mêmes options
de compilation pour être sûr - une DLL peut être une bonne
idée).
[...]
o_O
Et chargée à la même adresse, la DLL, non ?
Bon sérieux, ça existe dans la vraie vie
un truc pareil ? Pas taper, je demande.
Ca m'a l'air quand même un poil plus simple de
faire de simples structures de données, avec
des offsets au lieu de pointeurs si nécessaires, puis
de les encapsuler par des vrais objets dans chaque
process, non ?
Il faut qu'il soit dans chacun des programmes (compilés avec exactement le même compilateur et les mêmes options de compilation pour être sûr - une DLL peut être une bonne idée).
[...]
o_O
Et chargée à la même adresse, la DLL, non ?
Bon sérieux, ça existe dans la vraie vie un truc pareil ? Pas taper, je demande.
Ca m'a l'air quand même un poil plus simple de faire de simples structures de données, avec des offsets au lieu de pointeurs si nécessaires, puis de les encapsuler par des vrais objets dans chaque process, non ?
adebaene
Thierry wrote in message news:...
Bonjour,
Arnaud Debaene a écrit :
> - Dans les conteneurs genre std::vector qui peuvent avoir une capacité > supérieure à leur taille courante, on alloue un buffer pour X objets > puis on créé / détruit des objets dans ce buffer selon les besoins. > > - Pour créer un objet dans une zone mémoire particulière, comme un > memory mapped file pour partager un objet entre plusieurs processus.
Ca marcherait aussi dans un data seg partagé de DLL ?
Si tu alloues statiquement dans ton data-seg un buffer suffisamment gros, oui ca devrait marcher.
Le pb que je vois c'est que c'est dans le new qu'est explicitement precisé où doit être creer l'objet.
Ben oui... Où voudrait-tu que ce soit?
Y'a moyen de combiner le placement avec la surcharge de l'operateur new pour que tous les objets d'un module soient créés dans un zone mémoire précise ?
Je ne suis pas certain de comprendre. Si la question est "est ce que je peux surcharger l'opérateur new avec placement pour une classe?", la réponse est oui. Cependant, tu n'as pas d'allocation à faire dans cet opérateur puisque le biffer est *déjà* fourni. Généralement, on fait dans une surcharge de placement-new du logging de création d'objet ou des choses de ce goût de là, mais pas d'allocation à proprement parler.
class X { public: //..... void* operator new(size_t, void* location) { //log de l'appel, vérifications diverses, ... return location; //pas d'allocation mémoire!! } };
Dans ce cas, il faut aussi définir un operator delete avec placement pour le cas particulier où le constructeur lève une exception, afin de défaire tout ce qu'aurait pu faire le new avec placement. Mais là on commence à s'aventurer dans les coins vraiment obscures et poussiéreux du C++!! :-) Voir http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/1995/N0642.pdf pour les détails gore.
Arnaud MVP - VC
Thierry <yarglah@com.invalid> wrote in message news:<XnF949370692B38Dpouletetcetc@212.27.42.66>...
Bonjour,
Arnaud Debaene a écrit :
> - Dans les conteneurs genre std::vector qui peuvent avoir une capacité
> supérieure à leur taille courante, on alloue un buffer pour X objets
> puis on créé / détruit des objets dans ce buffer selon les besoins.
>
> - Pour créer un objet dans une zone mémoire particulière, comme un
> memory mapped file pour partager un objet entre plusieurs processus.
Ca marcherait aussi dans un data seg partagé de DLL ?
Si tu alloues statiquement dans ton data-seg un buffer suffisamment
gros, oui ca devrait marcher.
Le pb que je vois c'est que c'est dans le new qu'est explicitement precisé
où doit être creer l'objet.
Ben oui... Où voudrait-tu que ce soit?
Y'a moyen de combiner le placement avec la
surcharge de l'operateur new pour que tous les objets d'un module soient
créés dans un zone mémoire précise ?
Je ne suis pas certain de comprendre. Si la question est "est ce que
je peux surcharger l'opérateur new avec placement pour une classe?",
la réponse est oui. Cependant, tu n'as pas d'allocation à faire dans
cet opérateur puisque le biffer est *déjà* fourni. Généralement, on
fait dans une surcharge de placement-new du logging de création
d'objet ou des choses de ce goût de là, mais pas d'allocation à
proprement parler.
class X
{
public:
//.....
void* operator new(size_t, void* location)
{
//log de l'appel, vérifications diverses, ...
return location; //pas d'allocation mémoire!!
}
};
Dans ce cas, il faut aussi définir un operator delete avec placement
pour le cas particulier où le constructeur lève une exception, afin de
défaire tout ce qu'aurait pu faire le new avec placement. Mais là on
commence à s'aventurer dans les coins vraiment obscures et poussiéreux
du C++!! :-)
Voir http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/1995/N0642.pdf
pour les détails gore.
> - Dans les conteneurs genre std::vector qui peuvent avoir une capacité > supérieure à leur taille courante, on alloue un buffer pour X objets > puis on créé / détruit des objets dans ce buffer selon les besoins. > > - Pour créer un objet dans une zone mémoire particulière, comme un > memory mapped file pour partager un objet entre plusieurs processus.
Ca marcherait aussi dans un data seg partagé de DLL ?
Si tu alloues statiquement dans ton data-seg un buffer suffisamment gros, oui ca devrait marcher.
Le pb que je vois c'est que c'est dans le new qu'est explicitement precisé où doit être creer l'objet.
Ben oui... Où voudrait-tu que ce soit?
Y'a moyen de combiner le placement avec la surcharge de l'operateur new pour que tous les objets d'un module soient créés dans un zone mémoire précise ?
Je ne suis pas certain de comprendre. Si la question est "est ce que je peux surcharger l'opérateur new avec placement pour une classe?", la réponse est oui. Cependant, tu n'as pas d'allocation à faire dans cet opérateur puisque le biffer est *déjà* fourni. Généralement, on fait dans une surcharge de placement-new du logging de création d'objet ou des choses de ce goût de là, mais pas d'allocation à proprement parler.
class X { public: //..... void* operator new(size_t, void* location) { //log de l'appel, vérifications diverses, ... return location; //pas d'allocation mémoire!! } };
Dans ce cas, il faut aussi définir un operator delete avec placement pour le cas particulier où le constructeur lève une exception, afin de défaire tout ce qu'aurait pu faire le new avec placement. Mais là on commence à s'aventurer dans les coins vraiment obscures et poussiéreux du C++!! :-) Voir http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/1995/N0642.pdf pour les détails gore.
Arnaud MVP - VC
Arnaud Debaene
Manuel Leclerc wrote:
Arnaud Debaene a écrit :
Manuel Leclerc wrote ...
on peut vraiment faire une chose pareille ?
Et oui! ;-)
Et le code, il est où ?
Il faut qu'il soit dans chacun des programmes (compilés avec exactement le même compilateur et les mêmes options de compilation pour être sûr - une DLL peut être une bonne idée).
[...]
o_O
Et chargée à la même adresse, la DLL, non ?
Pas nécessairement. Si elle est chargée à la même adresse, tu peux même te permettre d'utiliser des fonctions avec des v-ptrs (si on considère que les v-tables sont directement en dur dans le segment de code de la DLL)..
Bon sérieux, ça existe dans la vraie vie un truc pareil ? Pas taper, je demande.
ben oui, pourquoi pas...
Ca m'a l'air quand même un poil plus simple de faire de simples structures de données, avec des offsets au lieu de pointeurs si nécessaires, puis de les encapsuler par des vrais objets dans chaque process, non ?
La plupart du temps certainement; mais sur des systèmes où tu n'a pas la notion de threads (que des processus - certains *nix par exemple), ca peut être intéressant.
Arnaud MVP - VC
Manuel Leclerc wrote:
Arnaud Debaene a écrit :
Manuel Leclerc wrote ...
on peut vraiment faire une
chose pareille ?
Et oui! ;-)
Et le code, il est où ?
Il faut qu'il soit dans chacun des programmes (compilés
avec exactement le même compilateur et les mêmes options
de compilation pour être sûr - une DLL peut être une bonne
idée).
[...]
o_O
Et chargée à la même adresse, la DLL, non ?
Pas nécessairement. Si elle est chargée à la même adresse, tu peux même te
permettre d'utiliser des fonctions avec des v-ptrs (si on considère que les
v-tables sont directement en dur dans le segment de code de la DLL)..
Bon sérieux, ça existe dans la vraie vie
un truc pareil ? Pas taper, je demande.
ben oui, pourquoi pas...
Ca m'a l'air quand même un poil plus simple de
faire de simples structures de données, avec
des offsets au lieu de pointeurs si nécessaires, puis
de les encapsuler par des vrais objets dans chaque
process, non ?
La plupart du temps certainement; mais sur des systèmes où tu n'a pas la
notion de threads (que des processus - certains *nix par exemple), ca peut
être intéressant.
Il faut qu'il soit dans chacun des programmes (compilés avec exactement le même compilateur et les mêmes options de compilation pour être sûr - une DLL peut être une bonne idée).
[...]
o_O
Et chargée à la même adresse, la DLL, non ?
Pas nécessairement. Si elle est chargée à la même adresse, tu peux même te permettre d'utiliser des fonctions avec des v-ptrs (si on considère que les v-tables sont directement en dur dans le segment de code de la DLL)..
Bon sérieux, ça existe dans la vraie vie un truc pareil ? Pas taper, je demande.
ben oui, pourquoi pas...
Ca m'a l'air quand même un poil plus simple de faire de simples structures de données, avec des offsets au lieu de pointeurs si nécessaires, puis de les encapsuler par des vrais objets dans chaque process, non ?
La plupart du temps certainement; mais sur des systèmes où tu n'a pas la notion de threads (que des processus - certains *nix par exemple), ca peut être intéressant.