Appel à _freea vraiment nécessaire?

Je développe sous Windows avec DevStudio, en C / C ++ non géré.

Je veux allouer de la mémoire sur la stack au lieu du tas car je ne veux pas avoir à gérer cette mémoire manuellement (je connais les pointeurs intelligents et toutes ces choses. J’ai un cas très spécifique d’allocation de mémoire dont j’ai besoin à traiter), similaire à l’utilisation des macros A2W () et W2A ().

_alloca fait ça, mais c’est déconseillé. Il est suggéré d’utiliser plutôt malloca . Mais la documentation de _malloca dit qu’un appel à ___freea est obligatoire pour chaque appel à _malloca. Cela va à l’encontre de mon objective d’utiliser _malloca, je vais plutôt utiliser malloc ou new.

Quelqu’un sait-il si je peux m’en sortir sans appeler _freea sans fuir et quels sont les impacts en interne?

Sinon, je finirai par utiliser simplement la fonction _alloca déconseillée.

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 allouer le tas au lieu de la stack. Si cela se produit et que vous n’appelez pas _freea, vous obtiendrez une fuite de mémoire.

En mode débogage, _malloca alloue TOUJOURS 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 au lieu de _alloca, et cela devrait avoir un sens.


Modifier:

Il y a eu des commentaires suggérant que la personne alloue simplement sur le tas, et utilise des pointeurs intelligents, etc.

Il y a des avantages à emstackr des allocations, que _malloca vous fournira, il y a donc des raisons de vouloir le faire. _alloca fonctionnera de la même manière, mais risque beaucoup plus de provoquer un débordement de stack ou un autre problème, et ne fournit malheureusement pas de bonnes exceptions, mais tend plutôt à détruire votre processus. _malloca est beaucoup plus sûr à cet égard et vous protège, mais le coût est que vous avez toujours besoin de libérer de la mémoire avec _freea car il est possible (mais peu probable en mode release) que _malloca choisisse d’allouer le tas au lieu de la stack.

Si votre seul but est d’éviter d’avoir à libérer de la mémoire, je vous recommande d’utiliser un pointeur intelligent qui gérera la libération de mémoire pour vous lorsque le membre sortira du champ d’application. Cela affecterait la mémoire sur le tas, mais soyez prudent et vous évitez de devoir libérer de la mémoire. Cela ne fonctionnera qu’en C ++ – si vous utilisez plain ol ‘C, cette approche ne fonctionnera pas.

Si vous essayez d’affecter à la stack pour d’autres raisons (généralement des performances, car les allocations de stack sont très, très rapides), je vous recommande d’utiliser _malloca et de vivre avec le fait d’appeler _freea sur vos valeurs.

Une autre chose à considérer est d’utiliser une classe RAII pour gérer l’allocation – bien sûr, cela n’est utile que si votre macro (ou autre) peut être restreinte à C ++.

Si vous voulez éviter de tomber sur le tas pour des raisons de performances, jetez un coup d’œ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 allouera sur la stack à moins que votre demande de taille d’exécution dépasse une taille spécifiée au moment du compilateur – vous obtenez donc la vitesse sans allocation de tas pour la majorité des allocations (si vous redimensionnez le modèle à droite), cette taille.

Comme STLsoft a beaucoup de mal à gérer les problèmes de portabilité, vous pouvez regarder une version plus simple de auto_buffer<> décrite dans le livre de Wilson, “Imperfect C ++”.

Je l’ai trouvé très pratique dans un projet embarqué.

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

J’ai déjà répondu à cette question, mais j’ai raté 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 se libérerait automatiquement.

Dans debug, c’est bien, car il alloue toujours sur le tas. Cependant, dans la version, il alloue sur la stack et, à son retour du constructeur, le pointeur de la stack a été réinitialisé et la mémoire perdue.

J’y suis retourné et j’ai adopté une approche différente, en combinant l’utilisation d’une macro (eurgh) pour allouer la mémoire et instancier un object qui appellera automatiquement _freea sur cette mémoire. Comme c’est une macro, elle est allouée dans le même frame de stack 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 de l’appel de macro suivant, et il est libéré lorsque la classe instanciée sort de la scope:

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

Toutes mes excuses pour avoir posté quelque chose qui était clairement faux!

Si votre préoccupation est de libérer de la mémoire temporaire, et que 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 est hors de scope?

 template  class TempMem { TempMem(size_t size) { mAddress = new T[size]; } ~TempMem { delete [] mAddress; } T* mAddress; } void foo( void ) { TempMem buffer(1024); // alternatively you could override the T* operator.. some_memory_stuff(buffer.mAddress); // temp-mem auto-freed } 

Si vous utilisez _malloca() vous devez appeler _freea() pour empêcher la fuite de mémoire car _malloca() peut effectuer l’allocation soit sur stack, soit sur tas. Il a recours à l’allocation sur le tas si la taille donnée dépasse la valeur_ALLOCA_S_THRESHOLD. Ainsi, il est plus sûr d’appeler _freea() qui ne fera rien si l’allocation se produisait sur la stack.

Si vous utilisez _alloca() qui semble être obsolète à ce jour; il n’est pas nécessaire d’appeler _freea() car l’allocation se produit sur la stack.