2009-04-09 4 views
8

Je développe sur Windows avec DevStudio, en C/C++ non géré. Je veux allouer de la mémoire sur la pile plutôt que sur le tas parce que je ne veux pas avoir à gérer cette mémoire manuellement (je connais les pointeurs intelligents et toutes ces choses). allocation de mémoire dont j'ai besoin), similaire à l'utilisation des macros A2W() et W2A().Appel à _freea vraiment nécessaire?

_alloca fait cela, mais il est déprécié. Il est suggéré d'utiliser malloca à la place. Mais la documentation _malloca dit qu'un appel à ___freea est obligatoire pour chaque appel à _malloca. Cela annule alors mon but d'utiliser _malloca, j'utiliserai malloc ou new à la place. Quelqu'un sait-il si je peux m'en tirer sans appeler _freea sans fuite et quels sont les impacts internes?

Sinon, je vais finir par utiliser la fonction _alloca obsolète.

Répondre

13

Il est toujours important d'appeler _freea après chaque appel à _malloca.

_malloca est comme _alloca, mais ajoute des contrôles de sécurité supplémentaires et des améliorations pour votre protection. Par conséquent, _malloca peut être alloué sur le tas au lieu de la pile. Si cela se produit, et vous n'appelez pas _freea, vous obtiendrez une fuite de mémoire.

En mode de débogage, _malloca ALWAYS alloue sur le tas, donc devrait également être libéré.

Recherchez _ALLOCA_S_THRESHOLD pour plus de détails sur le fonctionnement des seuils, et pourquoi _malloca existe à la place de _alloca, et cela devrait être logique.


Edit:

Il y a eu des commentaires suggérant que la personne vient d'allouer sur le tas, et utiliser des pointeurs intelligents, etc.

Il y a des avantages à empiler des allocations, qui vous fournira _malloca , donc il y a des raisons de vouloir faire cela. _alloca fonctionnera de la même manière, mais il est beaucoup plus susceptible de provoquer un débordement de pile ou un autre problème, et malheureusement ne fournit pas de belles exceptions, mais a plutôt tendance à détruire votre processus. _malloca est beaucoup plus sûr à cet égard, et vous protège, mais le coût est que vous avez encore besoin de libérer votre mémoire avec _freea car il est possible (mais peu probable en mode de libération) que _malloca choisira d'allouer sur le tas au lieu de la pile. Si votre seul but est d'éviter d'avoir à libérer de la mémoire, je vous recommande d'utiliser un pointeur intelligent qui va gérer la libération de la mémoire pour vous lorsque le membre sort du champ d'application. Cela affecterait la mémoire sur le tas, mais soyez sûr, et vous empêchez d'avoir à libérer la mémoire. Cela ne fonctionnera qu'en C++, cependant - si vous utilisez un langage simple, cette approche ne fonctionnera pas. Si vous essayez d'allouer sur la pile pour d'autres raisons (typiquement les performances, puisque les allocations de pile sont très, très rapides), je vous recommande d'utiliser _malloca et de vivre avec le fait que vous devrez appeler _freea sur votre valeurs.

+1

Juste curieux, mais pourquoi les downvotes sur Mitch et mes messages? J'aimerais savoir pourquoi quelqu'un est en désaccord avec ce commentaire ... surtout s'il me manque quelque chose. –

1

Pour allouer de la mémoire sur la pile, déclarez simplement une variable du type et de la taille appropriés.

+0

pourquoi le downvote? L'affiche posait des questions sur la pile ... –

+0

Ce n'était pas mon downvote, mais je devine juste parce qu'il demandait spécifiquement _alloca/_malloca, qui ont des modèles d'utilisation de pile très différents des déclarations de variables standard. Personnellement, je vais vous voter aussi, parce que dans la plupart des cas, c'est ce que je fais si possible. –

+0

@Reed Copsey: merci. –

0

Si votre souci est d'avoir à libérer de la mémoire temporaire, et vous savez tout sur des choses comme les pointeurs intelligents alors pourquoi ne pas utiliser un modèle similaire où la mémoire est libérée quand elle sort de la portée?

template <class T> 
class TempMem 
{ 
    TempMem(size_t size) 
    { 
    mAddress = new T[size]; 
    } 

    ~TempMem 
    { 
    delete [] mAddress; 
    } 

    T* mAddress; 
} 

void foo(void) 
{ 
    TempMem<int> buffer(1024); 

    // alternatively you could override the T* operator.. 
    some_memory_stuff(buffer.mAddress); 

    // temp-mem auto-freed 
} 
3

Une autre chose à considérer est d'utiliser une classe RAII pour gérer l'allocation - bien sûr qui est seulement utile si votre macro (ou autre) peuvent être limités à C++.

Si vous voulez éviter de tomber sur le tas pour des raisons de performances, jetez un œil aux techniques utilisées par la classe de modèles auto_buffer<> de Matthew Wilson (http://www.stlsoft.org/doc-1.9/classstlsoft_1_1auto__buffer.html). Cela va allouer sur la pile à moins que votre demande de taille d'exécution dépasse une taille spécifiée au moment du compilateur - donc vous obtenez la vitesse de pas d'allocation de tas pour la majorité des allocations (si vous dimensionnez le template), mais tout fonctionne correctement. cette taille.

Depuis STLsoft a beaucoup de cochonneries pour faire face aux problèmes de portabilité, vous pouvez regarder une version plus simple de auto_buffer<> qui est décrit dans le livre de Wilson, "Imperfect C++".

je l'ai trouvé très pratique dans un projet intégré .

+1

+1 sur la suggestion auto_buffer <>. C'est fondamentalement faire ce que _malloca fait au lieu de _alloca sur windows. Il y a une vérification pour vous assurer que vous ne couperez pas votre limite de pile, et il fera des allocations de tas si nécessaire au lieu des allocations de pile. Cela fonctionne en C, cependant. –

1

J'ai déjà répondu à cette question, mais j'avais manqué quelque chose de fondamental qui signifiait que cela ne fonctionnait qu'en mode débogage. J'ai déplacé l'appel à _malloca dans le constructeur d'une classe qui serait auto-libre. En debug c'est bien, car il alloue toujours sur le tas. Cependant, en release, il alloue sur la pile, et au retour du constructeur, le pointeur de pile a été réinitialisé, et la mémoire perdue.

Je suis retourné et j'ai pris une approche différente, résultant en une combinaison d'utiliser une macro (eurgh) pour allouer la mémoire et instancier un objet qui appellera automatiquement _freea sur cette mémoire. Comme c'est une macro, elle est allouée dans le même cadre de pile, et fonctionnera donc en mode release. C'est aussi pratique que ma classe, mais légèrement moins agréable à utiliser.

j'ai fait ce qui suit:

class EXPORT_LIB_CLASS CAutoMallocAFree 
{ 
public: 
    CAutoMallocAFree(void *pMem) : m_pMem(pMem) {} 
    ~CAutoMallocAFree() { _freea(m_pMem); } 

private: 
    void *m_pMem; 

    CAutoMallocAFree(); 
    CAutoMallocAFree(const CAutoMallocAFree &rhs); 
    CAutoMallocAFree &operator=(const CAutoMallocAFree &rhs); 
}; 

#define AUTO_MALLOCA(Var, Type, Length) \ 
    Type* Var = (Type *)(_malloca((Length) * sizeof (Type))); \ 
    CAutoMallocAFree __MALLOCA_##Var((void *) Var); 

De cette façon, je peux allouer à l'aide l'appel de macro suivant, et il est libéré lorsque la classe instanciée est hors de portée:

  AUTO_MALLOCA(pBuffer, BYTE, Len); 
      Ar.LoadRaw(pBuffer, Len); 

Mes excuses pour l'affichage quelque chose qui était clairement faux!

0

Si vous utilisez _malloca(), vous devez appeler le _freea() pour éviter les fuites de mémoire car _malloca() peut effectuer l'allocation sur la pile ou sur le tas. Il a recours à l'affectation sur tas si la taille donnée dépasse la valeur de _ALLOCA_S_THRESHOLD. Ainsi, il est plus sûr d'appeler le _freea() qui ne fera rien si l'allocation se produit sur la pile.

Si vous utilisez _alloca() qui semble être obsolète à compter d'aujourd'hui; il n'y a pas besoin d'appeler _freea() car l'allocation se passe sur la pile.

Questions connexes