web-dev-qa-db-fra.com

pinvokestackimbalance - comment puis-je résoudre ce problème ou le désactiver?

Je viens de passer à vs2010 de vs2008. Exactement la même solution, sauf que maintenant, chaque appel unique à une DLL C++ génère une exception "pinvokestackimbalance".

Cette exception ne se déclenche pas en 2008. J'ai un accès complet à la DLL C++ et à l'application appelante. Il ne semble pas y avoir de problème avec le pinvoke, mais ce problème rend impossible le débogage d'autres problèmes; le IDE s'arrête constamment pour me parler de ces choses.

Par exemple, voici la signature C #:

    [DllImport("ImageOperations.dll")]
    static extern void FasterFunction(
        [MarshalAs(UnmanagedType.LPArray)]ushort[] inImage, //IntPtr inImage, 
        [MarshalAs(UnmanagedType.LPArray)]byte[] outImage, //IntPtr outImage, 
        int inTotalSize, int inWindow, int inLevel);

Voici à quoi cela ressemble du côté C++:

#ifdef OPERATIONS_EXPORTS
#define OPERATIONS_API __declspec(dllexport)
#else
#define OPERATIONS_API __declspec(dllimport)
#endif
extern "C" {


OPERATIONS_API void __cdecl FasterFunction(unsigned short* inArray, 
                                       unsigned char* outRemappedImage,
                                       int inTotalSize, 
                                       int inWindow, int inLevel);

}

Quelle est la différence entre vs2010 et vs2008 qui entraînerait la levée de ces exceptions? Dois-je ajouter un autre ensemble de paramètres à la directive DllImport?

70
mmr

Tout d'abord, comprenez que le code est incorrect (et l'a toujours été). Le "pInvokeStackImbalance" n'est pas une exception en soi, mais un assistant de débogage géré. Il était désactivé par défaut dans VS2008, mais beaucoup de gens ne l'ont pas activé, il est donc activé par défaut dans VS2010. Le MDA ne s'exécute pas en mode Release, il ne se déclenchera donc pas si vous construisez pour la release.

Dans votre cas, la convention d'appel est incorrecte. DllImport par défaut à CallingConvention.WinApi, qui est identique à CallingConvention.StdCall pour le code de bureau x86. Il doit s'agir de CallingConvention.Cdecl.

Cela peut être fait en modifiant la ligne [DllImport("ImageOperations.dll")] pour qu'elle soit:

[DllImport("ImageOperations.dll", CallingConvention = CallingConvention.Cdecl)]

Pour plus d'informations, consultez cette référence MSDN

133
Stephen Cleary

Pour le désactiver:

  1. CTRL + ALT + E
  2. Sous "Assistants de débogage gérés", décochez PInvokeStackImbalance.
38
JGogel

Mieux vaut résoudre ce problème ce n'est pas très difficile ici. Je mentionne certaines des méthodes, cela peut être le même que certains de mes amis mentionnés ci-dessus. Je travaille avec PCSC une application de carte à puce que je passe environ une semaine, je suis énervé, beaucoup de changements ont finalement trouvé les solutions.

Pour moi, son travail avec PInvoke Extension que j'ai installé pour VS2010, vous pouvez le télécharger ici http://www.red-gate.com/products/dotnet-development/pinvoke/

Téléchargez-le et installez-le, fermez Visual Studio et ouvrez-le à nouveau, vous pouvez trouver l'extension dans la barre de menus. enter image description here

Si l'erreur est due à une signature qui ne correspond pas, cliquez simplement sur PInvoke.net> Insérer des signatures PInvoke

La nouvelle fenêtre apparaîtra comme ci-dessous enter image description here

Entrez le nom de la DLL et cliquez sur Rechercher, vous pouvez voir toutes les fonctions de cette DLL dans la fenêtre de résultats de recherche, cliquez sur la fonction, vous obtiendrez une signature pour cette fonction particulière.

Utilisez cette signature et vous devez modifier vos programmes en fonction de cette signature, principalement le type de données.

Cela résout mon problème, vous pourriez avoir un problème différent comme callConvention ou des attributs supplémentaires à spécifier lors de l'importation de la DLL.

Codage heureux Soyez bien!

8
Vijay Kumbhoje

J'ai également rencontré ce problème lors de l'utilisation de VS2010. Qu'est-ce que c'est: Visual Studio utilise par défaut du code 64 bits pour "n'importe quel processeur". Les pointeurs vers des variables (par exemple des chaînes) deviennent désormais 64 bits lors de l'appel de vos DLL externes, alors que toutes vos DLL fiables et fiables utilisent des pointeurs 32 bits.

Ne présumez pas qu'il y a un problème avec vos Dll, il n'y en a pas.

Modifiez vos paramètres VS pour générer du code X86 comme celui-ci (versions Express de C #)

  1. allez dans Outils -> Options.
  2. Dans le coin inférieur gauche de la boîte de dialogue Options, cochez la case "Afficher tous les paramètres".
  3. Dans l'arborescence de gauche, sélectionnez "Projets et solutions".
  4. Dans les options sur la droite, cochez la case qui indique "Afficher les configurations de construction avancées".
  5. Cliquez sur OK.
  6. Allez dans Build -> Configuration Manager ...
  7. Dans la colonne Plate-forme à côté de votre projet, cliquez sur la zone de liste déroulante et sélectionnez "".
  8. Dans le paramètre "Nouvelle plate-forme", choisissez "x86".
  9. Cliquez sur OK.
  10. Cliquez sur Fermer.

Je remarque également que, même si les ordinateurs ont doublé de puissance tous les 12 mois, mon ordinateur actuel avec 1 Go de RAM ne semble pas plus rapide que mon premier 486 avec 4 Mo. Ne vous inquiétez pas de l'utilisation de code 64 bits, cela ne sera ni plus rapide ni meilleur car il est construit sur une énorme tour de ballonnement orientée objet.

3
penguinman

J'ai essayé d'appeler la DLL avec le CallingConvention est ThisCall et cela a fonctionné pour moi. Voici mon code de travail avec BLOB MS Sql Server.

[DllImport("sqlncli11.dll", SetLastError = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.ThisCall)]
            private static extern SafeFileHandle OpenSqlFilestream(
                        string FilestreamPath,
                        UInt32 DesiredAccess,
                        UInt32 OpenOptions,
                        byte[] FilestreamTransactionContext,
                        UInt32 FilestreamTransactionContextLength,
                        Int64 AllocationSize);

Plus d'informations sur: https://msdn.Microsoft.com/en-us/library/system.runtime.interopservices.callingconvention (v = vs.110) .aspx

0
Hao Svit