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

Windows Discussion :

VirtualAlloc, HeapAlloc, GlobalAlloc : que choisir?


Sujet :

Windows

  1. #1
    Membre habitué Avatar de Crisanar
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    162
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2004
    Messages : 162
    Points : 137
    Points
    137
    Par défaut VirtualAlloc, HeapAlloc, GlobalAlloc : que choisir?
    Bonjour à tous,
    Je suis en train de développer une applic qui utilise une liste liée dynamique dont chaque élément est une structure de type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    DL_element struct
       Val      DWORD ?
       pNext DWORD ?
    DL_element ends
    Pour créer dynamiquement chaque élément j'utilise VirtualAlloc. Mais j'ai cru lire que VirtualAlloc arrondi chaque allocation à la taille d'une page.
    Or ma liste peut contenir énormément d'éléments donc si a chaque élément j'utilise 4096 bytes (taille d'une page sur mon ordi si je ne me suis pas trompé), j'aurais vite rempli la mémoire.
    Que me conseillez-vous d'utiliser?

    Merci d'avance,
    Crisanar

  2. #2
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 751
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 751
    Points : 10 670
    Points
    10 670
    Billets dans le blog
    3
    Par défaut
    Oui il vaut mieux passer par le tas.
    http://msdn.microsoft.com/library/en-us/dngenlib/html/msdn_virtmm.asp
    mais dans un tel cas, il faudrait créer ton propre allocateur qui gère un pool d'éléments. Les langages de haut niveau gèrent très bien les listes chainées...

  3. #3
    Membre habitué Avatar de Crisanar
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    162
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2004
    Messages : 162
    Points : 137
    Points
    137
    Par défaut
    Merci pour ta réponse
    Je sais que je devrais arreter l'ASM mais je n'arrive pas à m'en séparer

  4. #4
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    GlobalAlloc, le plus simple.
    HeapAlloc, un peu plus compliqué, mais probablement plus performant.

    Sinon, tu peux te faire ta propre gestion de mémoire. Voici un début pour t'inspirer.
    H:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    struct SVarBlock {
    	SVarBlock *s_next;
    	//char strBuf[];
    	};
    
    inline void InitBlocks(SVarBlock & vb)
    	{ vb.s_next=(SVarBlock *)0; }
    
    void * NewBlock(SVarBlock & vb,unsigned blockSize);
    
    void DestroyBlocks(SVarBlock & vb);
    
    int DeleteBlock(SVarBlock & vb,void *block);
    CPP:
    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
    void * NewBlock(SVarBlock & vb,unsigned blockSize)
    {
    SVarBlock *pb=(SVarBlock *)malloc(sizeof(SVarBlock)+blockSize);
    if (pb) {
    	pb->s_next=vb.s_next;
    	vb.s_next=pb;
    	return pb+1;
    	}
    return 0;
    }
    
    void DestroyBlocks(SVarBlock & vb)
    {
    SVarBlock *pb=vb.s_next;
    while (pb!=(SVarBlock *)0) {
    	SVarBlock *temp=pb->s_next;
    	free(pb);
    	pb=temp;
    	}
    vb.s_next=NULL;
    }
    
    int DeleteBlock(SVarBlock & vb,void *block)
    {
    SVarBlock **ppb=&vb.s_next;
    SVarBlock *bl=((SVarBlock *)block)-1;
    while (*ppb!=(SVarBlock *)0) {
    	if (*ppb==bl) {
    		*ppb=bl->s_next;
    		free(bl);
    		return 1;
    		}
    	ppb=&(*ppb)->s_next;
    	}
    return 0;
    }

  5. #5
    Membre habitué Avatar de Crisanar
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    162
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2004
    Messages : 162
    Points : 137
    Points
    137
    Par défaut
    Salut camboui,
    Merci pour ta réponse
    Lorsque tu dis faire ma propre gestion mémoire, je ne comprend pas très bien, malloc et free sont des fonctions du CPP mais elles appellent des fonctions de Windows, donc mis à part le fait de ne pas me tracasser des APIs à utiliser je ne vois pas trop l'intéret d'utiliser ces fonctions.

    Au fait, quel avantage à utiliser un malloc par rapport à un new?

    Aurelien.Regat-Barrel : je viens de relire ton post
    il faudrait créer ton propre allocateur qui gère un pool d'éléments
    Je ne comprends pas ce que tu veux dire, tu peux m'en dire un peu plus?

    Merci à tous
    Crisanar

  6. #6
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Faut lire entre les lignes...
    J'avais déjà remarqué le pragmatisme excessif du forum

    Tu peux/devrais bien sûr remplacer malloc() et free() par GlobalAlloc(GMEM_FIXED,) et GlobalFree().

    new fait un appel à malloc en interne.

    Aurélien a été assez clair je pense. Voici un exemple de pool, en complément du précédant code.
    H:
    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
    class MemoryCollection
    {
    	struct SCell
    	{
    		SCell *s_next;
    		//char s_data[dataSize !!! -sizeof(SCell *)];
    	};
    	SVarBlock f_vb;
    	SCell *f_freeCells;
    	unsigned f_cellsPerBlock,f_cellsUsedCount,f_cellSize;
    
    	void Destroy();
    	int AllocCells();
    public:
    	MemoryCollection();
    	MemoryCollection(unsigned cpBlock,unsigned dataSize);
    	~MemoryCollection();
    	int Init(unsigned cpBlock,unsigned dataSize);
    	unsigned Count()
    		{ return f_cellsUsedCount; }
    	void *NewMem();
    	void DeleteMem(void *data);
    };
    
    
    template <class T> class MemoryCollectionTpl&#58; protected MemoryCollection
    &#123;
    public&#58;
    	MemoryCollectionTpl&#40;&#41;
    		&#58;MemoryCollection&#40;&#41; &#123;&#125;
    	MemoryCollectionTpl&#40;unsigned cpBlock&#41;
    		&#58;MemoryCollection&#40;cpBlock,sizeof&#40;T&#41;&#41; &#123;&#125;
    	int Init&#40;unsigned cpBlock&#41;
    		&#123; return MemoryCollection&#58;&#58;Init&#40;cpBlock,sizeof&#40;T&#41;&#41;; &#125;
    	unsigned Count&#40;&#41;
    		&#123; return MemoryCollection&#58;&#58;Count&#40;&#41;; &#125;
    	T *NewMem&#40;&#41;
    		&#123; return &#40;T *&#41;MemoryCollection&#58;&#58;NewMem&#40;&#41;; &#125;
    	void DeleteMem&#40;T *data&#41;
    		&#123; MemoryCollection&#58;&#58;DeleteMem&#40;data&#41;; &#125;
    &#125;;
    CPP:
    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
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    MemoryCollection&#58;&#58;MemoryCollection&#40;&#41;
    &#58;f_freeCells&#40;NULL&#41;
    ,f_cellsPerBlock&#40;0u&#41;
    ,f_cellsUsedCount&#40;0u&#41;
    ,f_cellSize&#40;sizeof&#40;SCell&#41;&#41;
    &#123;
    InitBlocks&#40;f_vb&#41;;
    &#125;
    
    MemoryCollection&#58;&#58;MemoryCollection&#40;unsigned cpBlock,unsigned dataSize&#41;
    &#58;f_freeCells&#40;NULL&#41;
    ,f_cellsPerBlock&#40;cpBlock&#41;
    ,f_cellsUsedCount&#40;0u&#41;
    ,f_cellSize&#40;dataSize>sizeof&#40;SCell&#41;?dataSize&#58;sizeof&#40;SCell&#41;&#41;
    &#123;
    f_cellSize=&#40;f_cellSize+7u&#41; & ~7u;
    InitBlocks&#40;f_vb&#41;;
    AllocCells&#40;&#41;;
    &#125;
    
    MemoryCollection&#58;&#58;~MemoryCollection&#40;&#41;
    &#123;
    Destroy&#40;&#41;;
    &#125;
    
    void MemoryCollection&#58;&#58;Destroy&#40;&#41;
    &#123;
    DestroyBlocks&#40;f_vb&#41;;
    &#125;
    
    int MemoryCollection&#58;&#58;AllocCells&#40;&#41;
    &#123;
    SCell *cell=&#40;SCell *&#41;NewBlock&#40;f_vb,f_cellsPerBlock*f_cellSize&#41;;
    if &#40;!cell&#41; return 0;
    &#40;&#40;char *&&#41;cell&#41;+=&#40;f_cellsPerBlock-1&#41;*f_cellSize;
    for&#40;int i=f_cellsPerBlock-1;i>=0;i--&#41; &#123;
    	cell->s_next=f_freeCells;
    	f_freeCells=cell;
    	&#40;&#40;char *&&#41;cell&#41;-=f_cellSize;
    	&#125;
    return 1;
    &#125;
    
    int MemoryCollection&#58;&#58;Init&#40;unsigned cpBlock,unsigned dataSize&#41;
    &#123;
    Destroy&#40;&#41;;
    f_freeCells=NULL;
    f_cellsPerBlock=cpBlock;
    f_cellsUsedCount=0u;
    f_cellSize=dataSize>sizeof&#40;SCell&#41;?dataSize&#58;sizeof&#40;SCell&#41;;
    f_cellSize=&#40;f_cellSize+7u&#41; & ~7u;
    InitBlocks&#40;f_vb&#41;;
    return AllocCells&#40;&#41;;
    &#125;
    
    void *MemoryCollection&#58;&#58;NewMem&#40;&#41;
    &#123;
    if &#40;f_freeCells==&#40;SCell *&#41;0&#41;
    	if &#40;!AllocCells&#40;&#41;&#41;
    		return NULL;
    register SCell *newCell=f_freeCells;
    f_freeCells=newCell->s_next;
    f_cellsUsedCount++;
    return newCell;
    &#125;
    
    void MemoryCollection&#58;&#58;DeleteMem&#40;void *data&#41;
    &#123;
    if &#40;data==NULL&#41;
    	return;
    f_cellsUsedCount--;
    register SCell *cell=&#40;SCell *&#41;data;
    cell->s_next=f_freeCells;
    f_freeCells=cell;
    &#125;
    Voilà, l'ensemble de ce code permet de gérer de nombreuses petites allocations en allouant peu de gros blocks auprès du système. Je n'ai rien inventé, il est extrait/inspiré de MFC

    C'est du code assez bas niveau, à utiliser si on le comprend. Par exemple, il faut savoir que la mémoire n'est libérée auprès du système qu'en une fois, lors de la destruction de MemoryCollection. Mais les petites allocations/libérations au sein de MemoryCollection sont bien gérées (et très rapides).

  7. #7
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Citation Envoyé par Crisanar
    Lorsque tu dis faire ma propre gestion mémoire, je ne comprend pas très bien, malloc et free sont des fonctions du CPP mais elles appellent des fonctions de Windows, donc mis à part le fait de ne pas me tracasser des APIs à utiliser je ne vois pas trop l'intéret d'utiliser ces fonctions.
    Je te rappelle que le C est un langage sensé être indépendant du système. malloc et free existent depuis plus de 25 ans, l'API Windows est plus récente...
    Ensuite, on ne sait pas toujours ce qu'il y a derrière l'API de Windows. Fais un programme qui utilise et abuse des GlobalAlloc/FreeAlloc et fais-le tourner sous 95/98/Me, tu auras des performances catastrophiques... Il ira beaucoup mieux sous NT.
    Je sais, je sais, de nos jours nous sommes sous XP qui n'est pas trop mal foutu, mais on ne s'amuse pas à réécrire du code sous prétexte que l'OS s'est amélioré. D'autant que 98/Me est encore très répandu.

  8. #8
    Membre habitué Avatar de Crisanar
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    162
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2004
    Messages : 162
    Points : 137
    Points
    137
    Par défaut
    Salut camboui,
    Merci pour ce complément d'informations
    Je dois t'avouer que je n'ai pas compris ton code en CPP, j'ai qqes notions mais celà reste très basique.

    Lorsque je demandais des explications à Aurelien, je voulais en fait demander ce que voulait dire un 'pool d'éléments', je connais les 2 mots mais mis ensemble, je ne sais pas à quoi celà correspond

    Si je n'utilise pas les fonctions malloc, free, new, delete, c'est parce que je programme en ASM et que donc elles n'existent pas (à moins de les coder moi-même ou de les trouver, mais bon).
    Ma liste chainée étant déja créée, j'ai seulement remplcé les APIs VirtualAlloc et VirtualFree par HeapAlloc et HeapFree.

    Crisanar

  9. #9
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 751
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 751
    Points : 10 670
    Points
    10 670
    Billets dans le blog
    3
    Par défaut
    Je pensais au concept du pool comme (bien) expliqué ici (c'est pour du C++):
    http://www.boost.org/libs/pool/doc/concepts.html
    en gros, c'est un malloc maison spécilisé pour ton besoin. Il tient compte des spécificités de tes allocations, comme par exemple du fait que c'est toujours des objets de la même taille. C'est une couche supérieure à malloc/GlobalAlloc. En gros, ton pool alloue un gros bloc de mémoire avec malloc(), et il se le gère en interne de manière optimisée à ton besoin.
    D'ailleurs c'est ce que fait malloc vis à vis de HeapAlloc, et c'est ce que fait HeapAlloc vis à vis de VirtalAlloc...

  10. #10
    Membre habitué Avatar de Crisanar
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    162
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2004
    Messages : 162
    Points : 137
    Points
    137
    Par défaut
    Merci beaucoup pour le lien, j'aurais encore appris quelque chose aujourd'hui

  11. #11
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Citation Envoyé par Crisanar
    Salut camboui,
    Merci pour ce complément d'informations
    Je dois t'avouer que je n'ai pas compris ton code en CPP, j'ai qqes notions mais celà reste très basique.
    Oops, désolé.
    Je comprend que ce genre de code puisse être rébarbatif, même pour les plus chevronnés du C
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    int DeleteBlock&#40;SVarBlock & vb,void *block&#41; 
    &#123; 
    SVarBlock **ppb=&vb.s_next; 
    SVarBlock *bl=&#40;&#40;SVarBlock *&#41;block&#41;-1; 
    while &#40;*ppb!=&#40;SVarBlock *&#41;0&#41; &#123; 
       if &#40;*ppb==bl&#41; &#123; 
          *ppb=bl->s_next; 
          free&#40;bl&#41;; 
          return 1; 
          &#125; 
       ppb=&&#40;*ppb&#41;->s_next; 
       &#125; 
    return 0; 
    &#125;
    Mais ce n'est rien à coté de Perl ou XSLT

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Que choisir : Delphi ou C++ ?
    Par Gwipi dans le forum Débats sur le développement - Le Best Of
    Réponses: 30
    Dernier message: 18/07/2010, 11h43
  2. Que choisir ? C# , VB.NET, C++, Delphi ? pourquoi ?
    Par Louis-Guillaume Morand dans le forum Général Dotnet
    Réponses: 475
    Dernier message: 08/04/2010, 19h27
  3. Que choisir ? Delphi ou Java ?
    Par Jean-Yves dans le forum Débats sur le développement - Le Best Of
    Réponses: 89
    Dernier message: 19/04/2008, 15h40
  4. Web contre client/serveur que choisir??
    Par silvermoon dans le forum Débats sur le développement - Le Best Of
    Réponses: 41
    Dernier message: 24/01/2004, 15h53
  5. Que choisir ? Visual C++ ou Borland c++ builder ?
    Par ashram dans le forum Débats sur le développement - Le Best Of
    Réponses: 27
    Dernier message: 24/02/2003, 14h39

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