2010-11-02 3 views
1

Je rencontre une violation d'accès lors de l'appel d'une DLL dans LabVIEW. Appelons la DLL "extcode.dll". Je n'ai pas son code, il vient d'un fabricant externe.Violation d'accès dans l'appel LoadLibrary()

Courir dans Windbg, il est arrêté avec le message:

(724.1200): Access violation - code c0000005 (first chance) 
First chance exceptions are reported before any exception handling. 
This exception may be expected and handled. 
ntdll!RtlNewSecurityObjectWithMultipleInheritance+0x12a: 

Et pile appel:

ntdll!RtlNewSecurityObjectWithMultipleInheritance+0x12a 
ntdll!MD5Final+0xedfc 
ntdll!RtlFindClearBitsAndSet+0xdf4 
ntdll!RtlFindClearBitsAndSet+0x3a8 
ntdll!RtlFindClearBitsAndSet+0x4b9 
ntdll!RtlCreateProcessParametersEx+0x829 
ntdll!LdrLoadDll+0x9e 
KERNELBASE!LoadLibraryExW+0x19c 
KERNELBASE!LoadLibraryExA+0x51 
LabVIEW!ChangeVINameWrapper+0x36f5 
LabVIEW!ChangeVINameWrapper+0x3970 
LabVIEW!ExtFuncDynLibWrapper+0x211 

Notez que les dépendances de extcode.dll sont chargées avant violation d'accès.

La situation est aléatoire, mais quand cela arrive, tous les essais ultérieurs l'amènent.

Le code est une simple fonction LabVIEW appelant une fonction dans la DLL, et le prototype est super simple (int function(void)) donc il ne peut pas être une mauvaise configuration des paramètres d'appel, ni arithmétique de pointeur. J'ai vérifié chaque combinaison de conventions d'appel et de niveaux de vérification d'erreurs.

La DLL fonctionne parfaitement bien lorsqu'elle est appelée dans d'autres environnements (.NET et C).

Je trouve que RtlFindClearBitsAndSet est lié à des manipulations de tableau de bits

Qu'est-ce que vous faire penser à? Pensez-vous que c'est un problème dans extcode.dll, LabVIEW ou Windows? PS: J'utilise LabVIEW 2010 64 bits, sur Windows 7 64 bits (et extcode.dll est 64 bits). Je n'ai pas réussi à le reproduire sur un système 32 bits.

11/18 EDIT

Je fini par faire un exe autonome qui enveloppe la DLL; LabVIEW communique avec lui via des tuyaux. Cela fonctionne parfaitement, mais je ne comprends pas pourquoi charger une DLL dans LabVIEW peut tomber en panne.

Répondre

1

Si cela fonctionne correctement lorsque vous appelez de C, vous pouvez quitter travailler avec Windbg parce que la DLL est probablement OK. Quelque chose ne va pas avec la façon dont la DLL est appelée, et une fois que la DLL écrase une partie de la mémoire de LabView, tout est fini, même si cela peut prendre 1000 itérations avant que quelque chose ne devienne réellement kablooey.

Vérifiez d'abord vos conventions d'appel, C ou StdCall. C convention d'appel est la convention par défaut et StdCall est presque certainement ce que vous voulez. (Vérifiez le fichier d'en-tête DLL.) LabView 2009 a apparemment effectué une vérification automatique et une fixation des conventions d'appel, mais le passage à LLVM dans LV 2010 a rendu cela impossible; maintenant il n'y a plus que des chars.

S'il reste encore après avoir changé cela, vérifiez à nouveau vos arguments d'appel. ce que vous passez, les scalaires ou les données de pointeur? Vous ne pouvez pas accéder à la mémoire allouée par la DLL à partir de LabView sans faire des choses sournoises, bien que vous puissiez allouer de la mémoire (par exemple array byte) dans LabView et lui passer un pointeur pour la modifier. De même, si vous obtenez un pointeur (comme un refnum) d'un appel antérieur à DLL et le renvoyez, vérifiez la taille de votre pointeur. La fonction Call Library de LabView a maintenant un type "taille de pointeur entier", qui génère le type de taille appropriée selon qu'elle est invoquée en LabView 32 bits ou 64 bits. (C'est toujours 64 bits sur le fil, car cela doit être défini au moment de la compilation.) Le fait que votre DLL fonctionne en 32 suggère que c'est une possibilité.De plus, gardez à l'esprit que les structures C sont souvent alignées par le compilateur (C). Si vous passez un pointeur sur une structure composée d'un Uint8 et d'un UInt16, le compilateur C allouera 32 bits (ou peut-être même 64 bits) pour cela. Vous devrez remplir votre structure (cluster) dans LabView pour le faire correspondre, ou écrire une DLL wrapper pour assembler la structure.

-Rob

+0

Merci pour votre réponse: prototype est 'int func (void)', il ne peut donc pas s'agir d'une convention d'appel ou d'un problème de pointeur d'argument. – CharlesB

+1

Peut-être que vous devriez ouvrir un dossier de support avec NI. Ils sont assez bons pour aider avec des choses comme ça. –

0

Il est difficile de diagnostiquer à distance, mais voici quelques idées. Le fait que votre fonction ne prenne aucun argument signifie que la fonction est vraiment triviale, ou qu'il y a un état stocké dans la DLL qui prend en compte les appels de fonction précédents. Peut-être que le crash dans cette fonction est seulement un indicateur, et vous avez un problème avec un appel de fonction précédente? Y a-t-il une routine d'initialisation que vous n'appelez pas? Si vous ne rencontrez des problèmes lors de l'utilisation de labview 64 bit, mon premier doute serait qu'il y a un problème avec la version 64 bits de la DLL, mais si vous êtes sûr que vous n'avez aucun problème avec exactement les mêmes appels lors de l'utilisation de la DLL dans d'autres environnements, je suis perplexe. Une possibilité est que vous utilisez la mauvaise convention d'appel (stdcall vs cdecl) dans labview.

Avez-vous essayé d'importer la DLL et l'en-tête à l'aide de l'assistant d'importation labview? Cela pourrait aider à éviter les erreurs stupides avec les prototypes.

+0

Il n'y a pas de routine d'initialisation, elle peut fonctionner avec cet appel de fonction unique. Assistant d'importation labview essayé, convention d'appel différente, sans succès. Le prototype est mortellement simple ('int func (void)') donc ce n'est pas un problème de pointeur. Je suis perplexe aussi. – CharlesB

0

Une autre chose à essayer: faites un clic droit sur l'appel DLL, choisissez configurer et assurez-vous que vous exécutez dans le thread UI au lieu de tout thread. Parfois, cela aide.

1

Une violation d'accès (0xc0000005) sera également signalée si DEP (Prévention de l'exécution des données) est activé sur votre ordinateur et désapprouve quelque chose que votre binaire (EXE ou DLL) essaie de faire. DEP est généralement désactivée par défaut sous Windows XP, mais actif sous Windows Vista/Windows 7.

DEP est une mesure de sécurité pris en charge le matériel conçu pour empêcher le code malveillant d'exécuter certains octets qui ont été considérés comme auparavant « que quelques-uns Les données"; J'ai eu quelques run-ins avec lui, qui ont tous recompilé les binaires fautifs avec une version récente de Microsoft Visual Studio; cela vous permet de définir un indicateur qui définit si votre binaire prend en charge ou non DEP.

Quelques ressources utiles:

  • j'ai trouvé this MSDN blog entry très utile pour obtenir une compréhension de ce DEP est et ne
  • Vous pouvez également consulter t his technet article comment activer DEP et éteint sur Windows XP.
+0

Merci Edward; Je ne peux pas tester si c'était le problème puisque j'ai travaillé autour de lui en chargeant la DLL dans un processus séparé et en faisant des appels IPC. – CharlesB

Questions connexes