fuite de mémoire lors de l'appel du code non managé de code managé dans Windows 7
-
19-09-2019 - |
Question
Quand j'appelle un code C ++ non géré de mon code C #, il me semble avoir une sorte de fuite de mémoire.
Le C ++ lit les données à partir d'un fichier en utilisant ifstream.read, et l'écrit dans un vecteur.
Cela se produit uniquement après la mise à niveau vers Windows 7, ne se produit pas sur Vista, mais si j'utilise une version de la dll native qui a été compilé sur Vista, il ne change rien!
Si je lance le même code C ++ directement, sans le interope géré, il n'y a pas de fuite de mémoire!
Si je lance le processus de gestion, mais dans le processus de vshost, il n'y a pas de fuite de mémoire!
Voici la signature d'appel:
[DllImport(DllPath, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool MyMethod(
int x,
string y,
string z,
bool v,
bool w);
et natif:
MyDll_Export bool APIENTRY MyMethod(
int x,
const wchar_t* y,
const wchar_t* z,
bool v,
bool w)
Quand je l'appelle de C ++, je l'appelle comme ceci:
MyMethod(1, L"My String 1", L"My String 2", true, true)
Quand je regarde les compteurs de performance pour la mémoire gérées et non gérées, je vois que toute la mémoire vient du code non managé.
Considérant que le marshaling est assez simple, je ne comprends pas pourquoi il y a une différence entre appeler le C ++ directement ou par C #.
Je ne sais pas non pourquoi cela se produit uniquement sur Windows 7 (à la fois les installations Windows 3.5 SP1 ont .net).
Est-ce que quelqu'un a une idée quelle est la raison?
Aussi, si quelqu'un connaît un outil de profilage de la mémoire native qui fonctionne sur Windows 7, je serais heureux de savoir (pour l'instant je viens afficher sur la console toute allocation de mémoire explicite et il n'y a pas de différence).
La solution
Je suis sûr que le problème est lié à marshaling les types de données C # à leurs homologues C ++. Puisque vous Marshaling la valeur de retour bool à une valeur signée 1 octet, peut-être vous devriez faire la même chose aux arguments de la fonction? Le type C # bool est de 4 octets, peut-être que vous y une fuite de?
En outre, en spécifiant le type non géré pour les cordes peuvent aider.
[DllImport(DllPath, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool MyMethod(
int x,
[MarshalAs(UnmanagedType.LPWStr)]
[In] string y,
[MarshalAs(UnmanagedType.LPWStr)]
[In] string z,
[MarshalAs(UnmanagedType.I1)]
bool v,
[MarshalAs(UnmanagedType.I1)]
bool w);
Une explication pour le commentor:
En général, un zéro ou à un pointeur null valeur est convertie en faux, tout autre valeur est convertie en true.
...
Les 1998 C ++ Standard Library définit une spécialisation du vecteur modèle pour bool. La description de la classe indique que la la mise en œuvre devrait emballer le de sorte que tous les éléments bool seulement les utilisations un bit de mémoire.
Alors, à peu près tout ce que la valeur que vous utilisez, vous obtiendrez un c ++ booléen avec la valeur true ou false.
Autres conseils
Malheureusement, une fois que vous impliquez les chaînes, pas marshalling est simple.
Nous allons avoir besoin des données supplémentaires afin de vous aider à traquer ce problème. Pouvez-vous fournir les éléments suivants
- Méthode native Signature
- Comment la mémoire pour les chaînes gérées en code natif?
- Peut-être l'échantillon C ++ où vous utilisez l'API?
EDIT
Essayez la signature suivante. Cela indique au CLR de ne pas rassembler la mémoire dans les deux sens, mais passe plutôt que les données.
[DllImport(DllPath, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool MyMethod(
int x,
[In] string y,
[In] string z,
bool v,
bool w);
Je trouve l'utilisation du CLR Profiler utile lors de la recherche ma fuite de mémoire.
Êtes-vous sûr qu'il ya une fuite de mémoire?
Quelle est votre base pour déterminer la fuite de mémoire. Vous dites que vous pouvez le voir à partir des compteurs de performance, mais qu'est-ce que vous observez réellement? Voyez-vous une courbe ascendante coninously, ou qui se dépose à un niveau élevé? Une consommation élevée de mémoire est souvent confondue pour une fuite de mémoire.
BTW. Pouvez-vous vous poster C ++ définition de la fonction aussi bien?