40 votes

PInvokeStackImbalance appel C # à la fonction C ++ non gérée

Après le passage à VS2010, la gestion de débogage assistant affiche un message d'erreur relatif à un déséquilibre de la pile à partir d'un appel à un le C++ une fonction à partir d'une application en C#.

Le conventuelles suspects ne semblent pas être la cause du problème. Est-il autre chose que je doit vérifier? Le VS2008 construit dll C++ et C# application n'a jamais eu de problème, pas de bizarre ou de mystérieux insectes - oui, je sais, ça ne veut pas dire grand-chose.

Voici les choses qui ont été vérifiés:

  • Le nom de la dll est correct.
  • Le nom de point d'entrée est correcte et a été vérifié avec depends.exe - le code a utiliser le nom décomposé et il le fait.
  • La convention d'appel est correct.
  • Les tailles et tous les types semblent corrects.
  • Le jeu de caractères est correct.
  • Il ne semble pas y avoir de problèmes après en ignorant l'erreur et il n'y a pas un problème lors de l'exécution à l'extérieur du débogueur.

C#:

[DllImport("Correct.dll", EntryPoint = "SuperSpecialOpenFileFunc", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true)]
public static extern short SuperSpecialOpenFileFunc(ref SuperSpecialStruct stuff);

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct SuperSpecialStruct
{
   public int field1;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
   public string field2;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
   public string field3;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
   public string field4;
   public ushort field5;
   public ushort field6;
   public ushort field7;
   public short field8;
   public short field9;
   public uint field10;
   public short field11;
};

C++:

short SuperSpecialOpenFileFunc(SuperSpecialStruct * stuff);

struct SuperSpecialStruct
{
   int               field1;
   char              field2[256];
   char              field3[20];
   char              field4[10];
   unsigned short    field5;
   unsigned short    field6;
   unsigned short    field7;
   short             field8;
   short             field9;
   unsigned int      field10;
   short             field11;
};

Voici le message d'erreur:

Géré Assistant Débogage 'PInvokeStackImbalance' a détecté un problème dans 'application Gérée chemin".

Informations supplémentaires: Un appel à l' PInvoke fonction 'SuperSpecialOpenFileFunc' a déséquilibrée de la pile. C'est probable parce que la gestion de PInvoke signature ne correspond pas à la cible non géré la signature. Vérifiez que l'appel convention et les paramètres de l' PInvoke signature correspondre à la cible non géré signature.

63voto

Graviton Points 28358

Comme mentionné dans le commentaire de Dane Rose , vous pouvez utiliser __stdcall sur votre fonction C ++ ou déclarer CallingConvention = CallingConvention.Cdecl sur votre DllImport .

C'est la réponse qui résout mon problème.

9voto

John Knoeller Points 20754

Vous spécifiez stdcall en C # mais pas en C ++, une incompatibilité ici entraînera à la fois la fonction et l'appelant extraire les arguments de la pile.

D'autre part, il existe un commutateur de compilation qui activera stdcall en tant que convention d'appel par défaut, (-Gz) utilisez-vous cela?

Ou essayez ceci dans votre C ++

 short __stdcall SuperSpecialOpenFileFunc(SuperSpecialStruct * stuff);
 

3voto

Michael Points 34110

Vous ne spécifiez pas de remplissage dans votre déclaration C # de la structure, mais pas dans la version C ++. Puisque vous mélangez des tableaux de caractères qui ne sont pas tous des multiples de quatre et un nombre impair de shorts de 2 octets, le compilateur insère probablement un remplissage dans la structure et ajoute la fin.

Essayez d’encapsuler la structure dans un #pragma pack pour éviter tout remplissage.

 #pragma pack(push)
#pragma pack(1)

// The struct

#pragma pack(pop)
 

2voto

user351059 Points 21

Avait le même problème que décrit - application C ++ non gérée qui a parfaitement fonctionné pendant des années. Lorsque nous avons mis à niveau vers VS2010, nous avons commencé à recevoir des messages PInvokeStackUnbalanced.

l'ajout de "__stdcall" à la signature C ++, comme décrit ci-dessus, a résolu le problème.

1voto

Jelena Points 11

Avez-vous réussi à résoudre le problème? Je suis sur le point de développer une application dans VS2010, qui utiliserait un héritage C++ dll et fait quelques test de base - avec des types de chaînes, quelque chose comme ceci:

C++:

extern "C" __declspec(dllexport) LPCTSTR lazeisha(LPCTSTR input)
{
      return input;
}

C#:

namespace CPlusPlusFromDotNet
{
    class Program
    {
        [DllImport("lazeisha.dll", EntryPoint = "lazeisha")]
        public static extern String lazeisha(String s);

        static void Main(string[] args)
        {
            String test = lazeisha("Test string");
            Console.WriteLine(test);
        }
    }
}

Maintenant cela fonctionne parfaitement bien dans VS2008 mais dans VS2010-je obtenir le PInvokeStackImbalance problème. De plus, cela ne montre en mode de débogage. J'ai trouvé un commentaire sur l'un des forums sur une application qui est devenu instable à cause de la même erreur. Je préfère ne pas démarrer sur le projet si c'est une vraie question.

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