2009-06-25 2 views
4

J'ai écrit une DLL Delphi qui communique avec un programme tiers via COM. Certains utilisateurs signalent que le programme tiers se bloque à l'occasion. D'autres utilisateurs du logiciel d'une manière identique n'ont jamais connu de crash. Lorsque cet incident se produit, le programme tiers semble être simplement indisponible dans mon application DLL. Le fournisseur jure que c'est un problème avec la façon dont la DLL Delphi est codée, bien qu'ils n'aient pas vu le code source et ne puissent pas dire ce que fait la DLL pour provoquer le crash, mais ils savent que c'est "quelque chose". ". Mis à part le fait que je crois que le programme tiers ne devrait pas tomber en panne en raison d'un minuscule problème dans ma DLL, supposons qu'il y a quelque chose dans ma DLL qui doit être corrigé.L'application Delphi communique avec le programme qui finit par tomber en panne de temps en temps - Le vendeur blâme mon application Delphi

Comment est-ce que je peux déterminer comment mon application peut causer ceci? Est-ce que quelqu'un a de l'expérience en communication via COM avec un programme hypersensible comme celui-ci? Y at-il des choses communes à rechercher qui pourraient s'écraser le programme tiers?

Répondre

4
  1. Rendez le client heureux.
  2. Ne supposez pas que ce n'est pas votre DLL, il pourrait être. Même si "Autres utilisateurs du logiciel d'une manière identique n'ont jamais connu un crash", il pourrait être que avec des données différentes, il fait des choses différentes ...
  3. Je suggère que vous installez la journalisation dans un fichier texte une version de diagnostic "spéciale".
  4. Consignez tout, vos paramètres, vos exceptions et les étapes que vous suivez. Peut-être même le début et la fin de chaque fonction, et toutes les autres lignes.

Voilà comment cela pourrait ressembler ...

Loaded DLL 
Started MyFunction1 with parameters: 1,4,hello 
    1 
    2 
    ... 
    500 
Ended MyFunction1 

faire que ,,, j'avais configuration quelques fonctions (dans leur propre unité):

// opens a text file (fixed name), and appends to it. 
function InitializeLog; 

// closes the file 
function CloseLog;  

//add a log line. 
function Log(message:string='', startNewFunction:boolean:False); 

vous le feriez appeler comme ceci:

function MyFunction1(Integer,Integer,String); 
begin 
    try 
    Log('Loaded DLL'); 

    //use inttostr and do some string concats to get the params 
    Log('Started MyFunction1 with parameters: 1,4,hello',true); 

    //Then every other line: 
    Log; 
    //this would increment a global variable FuncLine:Integer 
    //and write it to the file.  

    except 
    On E:Exception (Log('***'+E.Message)); 
    end; 
end; 

Quelque chose comme cela devrait avoir un {$ DEFINE} pour permettre à ces fonctions de journalisation, pour activer/désactiver la journalisation des diagnostics.

This could also be useful.

2

Si leur programme se bloque lorsque vous utilisez leur interface publiée, je suis sûr que quelque chose ne va pas. Prouver cela est une autre chose, tout à fait.

Pouvez-vous reproduire le problème de manière fiable avec une petite application Delphi que vous pouvez donner au fournisseur? Voyant une défaillance reproductible pourrait aider à les convaincre qu'ils ont besoin de faire une correction. À tout le moins, cela pourrait aider à identifier ce qu'ils pensent que vous faites «mal» et vous dire comment le faire «bien».

Vous pouvez également essayer de dupliquer la panne en utilisant C# ou même VBScript.

+0

Je suis d'accord fortement. J'ai été dans cet endroit plusieurs fois avant et la solution la plus rapide a toujours été de créer un nouveau programme de test répétable et de le donner au fournisseur avec une source complète. Si possible, consignez toutes les interactions avec l'API (quels paramètres sont transmis et ce qui est renvoyé). – skamradt

+4

Le vendeur dit que la DLL de Dave est erronée. Le fournisseur est celui qui devrait faire le programme de test, pas Dave, puisque le fournisseur est celui qui a réellement vu le problème. Si ce n'est pas un programme de test, alors au moins une liste d'étapes à suivre pour démontrer le problème. –

+1

Je ne pense pas que le vendeur voit cela. Je pensais que c'était les clients de Dave. Quoi qu'il en soit, je suis d'accord que le fournisseur devrait intensifier et au moins aider à isoler le problème. Malheureusement, ils n'ont pas l'air très enthousiastes, donc il revient à Dave de les convaincre qu'il y a un problème ou, alternativement, de trouver un travail. Qui sait, en dupliquant le problème, il pourrait trouver qu'il fait une erreur après tout. Bottom line; Dave a ses clients à s'inquiéter. –

4

Regardez Quality Central pour le rapport 58409.

Il est sur le FPU Masque et dll.

Pour l'expliquer en bref:

Les réglages du masque FPU déterm comment les exceptions à virgule flottante sont traitées. Si vous avez par exemple un Applicaion_A (codé par un autre) qui charge Dll_A (également codé par d'autres) et Dll_B (codé par vous), et votre Dll change le masque FPU, alors cette modification est valable pour Application_A et Dll_A aussi. Prenons un exemple: Vous avez installé par exemple WinZIP, SubVersion etc. qui enregistre des fonctions supplémentaires dans l'explorateur de fichiers Windows (menu contextuel avec le bouton droit de la souris) et vous appelez maintenant TOpenDialog depuis votre application.exe, alors ces fonctions supplémentaires pourraient compromettre vos paramètres FPU.

Espérons que cela aide. (Indice supplémentaire: Sysinternal pour voir quelles sont les DLL chargées par votre application)

+0

Samuel - est-il un moyen de savoir si cela se produit dans ma situation? – Dave

+2

Enregistrez et restaurez le mot de contrôle pour que l'application affiche toujours la même valeur que celle qu'elle a toujours utilisée. Si cela guérit le problème, alors c'était la cause. –

3

Avez-vous envisagé d'utiliser MadExcept? Si vous observez l'erreur dans les méthodes d'interface, vous pouvez soit vous connecter à la pile d'appels, soit afficher une boîte de dialogue à l'utilisateur et renvoyer un EOleSysError standard à l'exe appelant.

Quelque chose comme ceci:

except 
    on e: Exception do 
    begin 
     MadExcept.HandleException(); 

     raise EOleSysError.Create('InitializeObject Failed', 
     ErrorNumberToHResult(1 + CODE_BASE), 1); 
    end; 

Si l'application se bloque, mais pas de ne pas jeter et exception, vous pouvez voir ce qui se passe en utilisant le madTraceProcess utilitaire MadExcept. Cela vous permettra de générer une pile d'appels pour l'application en cours d'exécution. Votre dll ne sera pas sur le fil principal, mais vous pourrez voir votre pile d'appels. C'est un bon moyen de savoir si votre DLL est en train de faire quoi que ce soit lorsque le blocage se produit.

J'ai une DLL COM qui interagit avec un exe qui n'utilise pas MadExcept et cette approche a bien fonctionné pour moi.

+0

Je cours EurekaLog dans la DLL et il ne soulève pas une exception lorsque l'application tierce se bloque. Autant que je sache, il n'est pas du tout annoncé quand il tombe en panne. – Dave

2

Si j'ai bien compris la situation, malheureusement, il n'y a pas grand chose à faire de votre côté si votre DLL ne plante pas et que le programme tiers appelé cesse d'être réactif. Le crash est dans leur code mais seulement déclenché par votre DLL l'appelant. Le journal de débogage devrait vraiment être fait dans leur application. Cependant, ce que vous pouvez faire est de consigner tous les appels que votre DLL fait à ce programme tiers avec les paramètres et quelques informations contextuelles.
Puis, regardant la dernière trace avant l'accident pourrait vous donner quelques informations ...

2

Je ne sais pas comment le travail madExcept etc, mais j'utilise jclDebug.pas + JclHookExcept.pas (bibliothèque JEDI JCL) une lot. Il fait un crochet API Windows, il attrape toutes les exceptions, même si vous faites quelque chose comme ça (!):

try 
    raise exception.create('test'); 
except 
    //eat exception 
end; 

Normalement, vous ne voyez pas cette exception parce qu'il est « mangé » ... Mais avec le crochet vous obtenez toutes les exceptions. Par exemple: j'ai une fois eu un "échec catastrophique" dans Midas.dll, et par l'intermédiaire du crochet j'ai vu une erreur de "connexion de base de données perdue" dans la DLL avant cette exception, ainsi j'ai su ce qui s'est produit. (btw: JclHookExcept.pas = hook, jclDebug.pas = trace de strack).

Je vois maintenant que JclHookExcept.pas a aussi une procédure "JclHookExceptionsInModule", donc vous pouvez forcer (?) À accrocher toutes les exceptions d'une bibliothèque spécifique ...

Une partie du code de démonstration:

procedure AnyExceptionNotify(ExceptObj: TObject; ExceptAddr: Pointer; OSException: Boolean); 
begin 
    //log exception 
end; 

initialization 
    // Start Exception tracking 
    JclStartExceptionTracking; 
    JclTrackExceptionsFromLibraries; 
    JclStackTrackingOptions := [stStack, stRawMode, stAllModules]; 
    // Assign notification procedure for hooked RaiseException API call. This 
    // allows being notified of any exception 
    JclAddExceptNotifier(AnyExceptionNotify); 
Questions connexes