web-dev-qa-db-fra.com

LocalAlloc Vs GlobalAlloc Vs malloc Vs new

J'ai cherché cela sur divers liens, mais le doute persiste.

Je ne comprends pas la différence entre LocalAlloc vs GlobalAlloc vs malloc vs new pour l'allocation de mémoire.

J'ai parcouru ce lien de MSDN:

Comparaison des méthodes d'allocation de mémoire

Veuillez expliquer la déclaration suivante:

La fonction malloc a l'inconvénient d'être dépendante de l'exécution. Le nouvel opérateur a l'inconvénient d'être dépendant du compilateur et dépendant de la langue

26
User1234

Extraits de OldNewThing de Raymond Chen

À l'époque de Windows 16 bits, la différence était significative.

Dans Windows 16 bits, la mémoire était accessible via des valeurs appelées "sélecteurs", chacune pouvant adresser jusqu'à 64 Ko. Il y avait un sélecteur par défaut appelé "sélecteur de données"; des opérations sur des "pointeurs proches" ont été effectuées par rapport au sélecteur de données. Par exemple, si vous aviez un pointeur proche p dont la valeur était 0x1234 et votre sélecteur de données était 0x012F, alors lorsque vous avez écrit * p, vous accédiez à la mémoire à 012F: 1234. (Lorsque vous déclariez un pointeur, il était proche par défaut. Vous deviez dire FAR explicitement si vous vouliez un pointeur éloigné.)

Important: les pointeurs proches sont toujours relatifs à un sélecteur, généralement le sélecteur de données.

La fonction GlobalAlloc a alloué un sélecteur qui pourrait être utilisé pour accéder à la quantité de mémoire que vous avez demandée. Vous pouvez accéder à la mémoire de ce sélecteur avec un "pointeur éloigné". Un "pointeur éloigné" est un sélecteur combiné avec un pointeur proche. (N'oubliez pas qu'un pointeur proche est relatif à un sélecteur; lorsque vous combinez le pointeur proche avec un sélecteur approprié, vous obtenez un pointeur éloigné.)

Chaque instance d'un programme et DLL a obtenu son propre sélecteur de données, connu sous le nom de HINSTANCE. Par conséquent, si vous aviez un pointeur proche p et y avez accédé via * p à partir d'un exécutable de programme, il a accédé à la mémoire par rapport à HINSTANCE de l'instance de programme. Si vous y avez accédé à partir d'une DLL, vous avez obtenu de la mémoire par rapport à HINSTANCE de votre DLL.

Par conséquent, dans Windows 16 bits, les fonctions LocalAlloc et GlobalAlloc étaient complètement différentes! LocalAlloc a renvoyé un pointeur proche, tandis que GlobalAlloc a renvoyé un sélecteur.

Les pointeurs que vous aviez l'intention de passer entre les modules devaient être sous la forme de "pointeurs éloignés" car chaque module a un sélecteur par défaut différent. Si vous vouliez transférer la propriété de la mémoire vers un autre module, vous deviez utiliser GlobalAlloc car cela permettait au destinataire d'appeler GlobalFree pour la libérer.

Même dans Win32, vous devez faire attention à ne pas confondre le tas local avec le tas global. La mémoire allouée par l'un ne peut pas être libérée par l'autre. Toutes les bizarreries sur les pointeurs proches et lointains ont disparu avec la transition vers Win32. Mais les fonctions de tas locales et les fonctions de tas globales sont néanmoins deux interfaces de tas distinctes.

De plus, le lien que vous avez spécifié indique clairement que,

À partir de Windows 32 bits, GlobalAlloc et LocalAlloc sont implémentés en tant que fonctions d'encapsuleur qui appellent HeapAlloc à l'aide d'une poignée vers le tas par défaut du processus, et HeapAlloc peut être chargé de lever une exception si la mémoire n'a pas pu être allouée, une capacité non disponible avec LocalAlloc.

Pour votre confusion sur malloc vs new , la réponse de Billy ONeal résume cela assez clairement.

Pour la différence entre malloc et HeapAlloc, la réponse combinée de David Heffernan et Luis Miguel Huapaya donne la solution parfaite:

  • malloc est portable, fait partie de la norme. malloc (et d'autres fonctions de tas d'exécution C) dépendent du module, ce qui signifie que si vous appelez malloc dans le code d'un module (c'est-à-dire une DLL), alors vous devez appeler free dans le code du même module ou vous pourriez subir une corruption de tas assez mauvaise.
  • HeapAlloc n'est pas portable, c'est une fonction API Windows. L'utilisation de HeapAlloc avec GetProcessHeap au lieu de malloc, y compris la surcharge des opérateurs new et delete pour en faire usage, vous permet de passer dynamiquement les objets alloués entre les modules et ne pas avoir à se soucier de la corruption de la mémoire si la mémoire est allouée dans le code d'un module et libérée dans le code d'un autre module une fois que le pointeur vers un bloc de mémoire a été transmis à un module externe.
21
Abhineet

GlobalAlloc et LocalAlloc sont d'anciennes fonctions de l'ère 16 bits. La différence était que vous deviez parfois pouvoir allouer de la mémoire uniquement utilisée dans votre segment (celui utilisé pointeurs), et parfois nécessaire d'allouer de la mémoire à partager avec d'autres processus et segments du système. Aujourd'hui, ces types transmettent sous une forme ou une autre aux fonctions HeapXxx, telles que HeapAlloc. Si vous écrivez du nouveau code et que vous devez éviter la liaison avec le runtime C, vous devez utiliser les fonctions HeapXxx à la place. Bien sûr, si vous appelez l'un de ces éléments, votre programme ne se compilera et ne s'exécutera que sous Windows.

malloc est "dépendante de l'exécution" dans la mesure où son utilisation nécessite une liaison avec l'exécution C (CRT). Le CRT est la bibliothèque qui contient toutes les autres fonctions de bibliothèque C standard, comme printf ou qsort. Vous pouvez écrire un programme API Win32 simple sans établir de lien avec cela (mais honnêtement, je ne vois pas pourquoi vous voudriez le faire dans un vrai logiciel).

new dépend du compilateur et dépend du langage dans la mesure où ils nécessitent un compilateur capable de compiler C++. (Et généralement new est implémenté en termes de malloc, donc il faudra probablement aussi utiliser le CRT)

17
Billy ONeal