200 votes

Que sont exactement les ressources non gérées ?

Je veux savoir ce que sont les ressources non gérées. Quelqu'un peut-il me donner une idée de base ?

1 votes

Voir aussi cette page, qui donne une explication fantastique et un modèle pour l'utilisation correcte de IDisposable, et comment prendre en compte les ressources non gérées : stackoverflow.com/questions/538060/

220voto

Andrew Russell Points 20217

Par ressources gérées, on entend essentiellement la "mémoire gérée" qui est gérée par le ramasseur d'ordures. Lorsque vous n'avez plus de références à un objet géré (qui utilise de la mémoire gérée), le ramasseur d'ordures libère (éventuellement) cette mémoire pour vous.

Les ressources non gérées sont alors tout ce que le ramasseur d'ordures ne connaît pas. Par exemple :

  • Ouvrir des dossiers
  • Connexions réseau ouvertes
  • Mémoire non gérée
  • Dans XNA : tampons de vertex, tampons d'index, textures, etc.

Normalement, vous voulez libérer ces ressources non gérées. avant vous perdez toutes les références que vous avez à l'objet qui les gère. Pour ce faire, vous appelez Dispose sur cet objet, ou (en C#) en utilisant la fonction using qui se chargera d'appeler Dispose pour vous.

Si vous négligez de Dispose de vos ressources non gérées correctement, le ramasseur d'ordures s'en chargera éventuellement pour vous lorsque l'objet contenant cette ressource sera ramassé (c'est la "finalisation"). Mais comme le ramasseur d'ordures ne connaît pas les ressources non gérées, il ne peut pas savoir à quel point il doit les libérer - il est donc possible que votre programme ait des performances médiocres ou qu'il manque complètement de ressources.

Si vous implémentez vous-même une classe qui gère des ressources non gérées, c'est à vous d'implémenter Dispose et Finalize correctement.

9 votes

La connexion à une base de données ouverte relève de quelle catégorie ? Gérée / Non gérée ?

9 votes

+1 Les autres réponses manquent le point important que vous appelez Dispose sur un géré qui gère en interne la libération de la ressource non gérée qu'il enveloppe (par exemple, un gestionnaire de fichier, un bitmap GDI+, ...) et que si vous accédez directement aux ressources non gérées (PInvoke, etc.), vous devez vous en charger.

3 votes

@Dev : Non géré - car le GC ne le sait pas (en supposant que vous n'utilisez pas une hypothétique base de données en mémoire gérée). Mais l'objet de connexion lui-même ne peut pas contenir une ressource non gérée. La connexion à la base de données utilise probablement un fichier ouvert ou une connexion réseau. quelque part - mais c'est possible qu'un autre objet (autre que l'objet de connexion) gère cette ressource non gérée (peut-être que votre bibliothèque de base de données met en cache les connexions). Vérifiez la documentation et voyez où il vous est demandé d'appeler Dispose ou utiliser using .

89voto

Martas Points 15

Certains utilisateurs classent les fichiers ouverts, les connexions aux bases de données, la mémoire allouée, les bitmaps, les flux de fichiers, etc. parmi les ressources gérées, d'autres parmi les ressources non gérées. Alors, sont-ils gérés ou non gérés ?

À mon avis, la réponse est plus complexe : lorsque vous ouvrez un fichier en .NET, vous utilisez probablement une classe intégrée de .NET, System.IO.File, FileStream ou autre. Comme il s'agit d'une classe .NET normale, elle est gérée. Mais c'est une enveloppe qui, à l'intérieur, fait le "sale boulot" (communiquer avec le système d'exploitation à l'aide de dlls Win32, appeler des fonctions de bas niveau ou même des instructions assembleur) qui ouvre réellement le fichier. Et ceci est, ce que .NET ne sait pas, non géré. Mais vous pouvez peut-être ouvrir le fichier par vous-même en utilisant des instructions d'assembleur et en contournant les fonctions de fichier de .NET. Dans ce cas, l'identifiant et le fichier ouvert sont des ressources non gérées.

C'est la même chose avec la base de données : si vous utilisez un assemblage de base de données, vous avez des classes comme DbConnection, etc. Mais elles enveloppent le "sale boulot", qui n'est pas géré (allouer de la mémoire au serveur, établir une connexion avec lui, ...). Si vous n'utilisez pas cette classe enveloppante et que vous ouvrez un socket réseau par vous-même et communiquez avec votre propre base de données étrange en utilisant quelques commandes, c'est non géré.

Ces classes de wrappers (File, DbConnection etc.) sont gérées, mais elles utilisent à l'intérieur des ressources non gérées de la même manière que vous, si vous n'utilisez pas les wrappers et faites le "sale boulot" par vous-même. Par conséquent, ces wrappers mettent en œuvre les schémas Dispose/Finalize. Il est de leur responsabilité de permettre au programmeur de libérer les ressources non gérées lorsque le wrapper n'est plus nécessaire, et de les libérer lorsque le wrapper est mis au rebut. Le wrapper sera correctement ramassé par le ramasseur d'ordures, mais les ressources non gérées à l'intérieur seront ramassées en utilisant le pattern Dispose/Finalize.

Si vous n'utilisez pas les classes wrapper intégrées de .NET ou de tiers et que vous ouvrez des fichiers par des instructions d'assembleur, etc. dans votre classe, ces fichiers ouverts ne sont pas gérés et vous DEVEZ implémenter le pattern dispose/finalise. Si vous ne le faites pas, il y aura une fuite de mémoire, une ressource verrouillée à jamais, etc., même si vous ne l'utilisez plus (opération de fichier terminée) ou même après la fin de votre application.

Mais votre responsabilité est également engagée lorsque vous utilisez ces wrappers. Pour ceux qui implémentent dispose/finalise (vous les reconnaissez, car ils implémentent IDisposable), implémentez également votre pattern dispose/finalise et disposez même ces wrappers ou donnez-leur un signal pour libérer leurs ressources non gérées. Si vous ne le faites pas, les ressources seront libérées après un temps indéfini, mais il est plus propre de les libérer immédiatement (fermez le fichier immédiatement et ne le laissez pas ouvert et bloqué pendant plusieurs minutes/heures). Ainsi, dans la méthode Dispose de votre classe, vous appelez les méthodes Dispose de tous les wrappers utilisés.

2 votes

Bien joué pour la clarté supplémentaire sur unmanaged vs managed resources

0 votes

Merci pour votre réponse. Quelles sont les classes pour lesquelles il est recommandé d'appeler Dispose ?

2 votes

C'est simple. Sur chaque classe que vous utilisez, vous devez vérifier, si elle implémente l'interface IDisposable. Si oui, alors si vous utilisez une telle classe dans une méthode (ex : ouverture du fichier, stockage du texte, fermeture du fichier), vous pouvez utiliser le pattern using() { }, qui appelle Dispose pour vous automatiquement. Si vous utilisez une telle classe dans plusieurs méthodes (ex : votre classe contient File, dans le constructeur elle ouvre le fichier, puis plusieurs méthodes ajoutent des logs...), alors vous devez implémenter l'interface IDisposable par votre classe, implémenter le pattern Dispose/Finalize et disposer correctement de l'objet de cette classe.

18voto

David Stratton Points 45298

Les ressources non gérées sont celles qui s'exécutent en dehors du moteur d'exécution .NET (CLR) (c'est-à-dire du code non .NET). Par exemple, un appel à une DLL dans l'API Win32, ou un appel à une .dll écrite en C++.

7voto

supercat Points 25534

Une "ressource non gérée" n'est pas une chose, mais une responsabilité. Si un objet possède une ressource non gérée, cela signifie que (1) une entité extérieure à l'objet a été manipulée d'une manière qui peut causer des problèmes si elle n'est pas nettoyée, et (2) l'objet possède les informations nécessaires pour effectuer ce nettoyage et est responsable de le faire.

Bien que de nombreux types de ressources non gérées soient très fortement associés à divers types d'entités du système d'exploitation (fichiers, handles GDI, blocs de mémoire alloués, etc.), il n'y a pas de type d'entité unique qui soit partagé par tous, si ce n'est la responsabilité du nettoyage. ), il n'y a pas de type d'entité unique qui soit partagé par tous, si ce n'est la responsabilité du nettoyage. Typiquement, si un objet a la responsabilité d'effectuer le nettoyage, il aura une méthode Dispose qui lui demandera d'effectuer tous les nettoyages dont il est responsable.

Dans certains cas, les objets prévoient la possibilité qu'ils soient abandonnés sans que personne n'ait appelé Dispose au préalable. La GC permet aux objets de demander une notification de leur abandon (en appelant une routine appelée Finalize), et les objets peuvent utiliser cette notification pour effectuer eux-mêmes le nettoyage.

Des termes comme "ressource gérée" et "ressource non gérée" sont, malheureusement, utilisés par différentes personnes pour signifier différentes choses ; franchement, je pense qu'il est plus utile de penser en termes d'objets comme n'ayant pas de responsabilité de nettoyage, ayant une responsabilité de nettoyage qui ne sera prise en charge que si Dispose est appelé, ou ayant une responsabilité de nettoyage qui devrait être prise en charge par Dispose, mais qui peut également être prise en charge par Finalize.

6voto

Marko Points 26030

La différence fondamentale entre une ressource gérée et non gérée est que le ramasseur d'ordures le ramasseur de déchets connaît toutes les ressources gérées, à un moment donné le GC viendra nettoyer toute la mémoire et les ressources associées à un objet géré. à un objet géré. Le GC ne connaît pas les ressources non gérées, comme les fichiers, les flux et les handles. comme les fichiers, les flux et les handles. Si vous ne les nettoyez pas explicitement dans votre code votre code, vous vous retrouverez avec des fuites de mémoire et des ressources verrouillées.

Volé à ici N'hésitez pas à lire l'intégralité de l'article.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X