Page 3 sur 6
Publié : mer. 12/août/2009 2:27
par Ollivier
EDIT: Je n'avais pas vu que tu as posté un autre message, mais ça n'annule en rien le fait de faire le test ci-dessus.
Une fois que tu auras vérifié cette histoire de libération de mémoire des chaînes, je pourrais me pencher sur le code sans risquer de perdre du temps.
Je t'ai mis un mp.
Ollivier
Publié : mer. 12/août/2009 11:24
par NY152
Ça plante l'application

Publié : mer. 12/août/2009 20:50
par Ollivier
Le bon côté des choses c'est que c'est maintenant que ça plante, et non pas quand la construction de ton application aura été fini depuis un certain temps et que ce crash te décevrait en pleine exécution par une fausse idée de manque de fiabilité des DLLs créées sous PB.
Je te remercie aussi d'être prompt à mes demandes. Car on avance de manière carrée, même si ça peut te sembler de plus en plus lourd!
(1)>> Est-ce que tu pourrais poster le code VB que tu as créé pour faire cette boucle de un million de tests, s'il-te-plaît?
Aussi, voici un autre test:
VB6 (ça reste rudimentaire)
Code : Tout sélectionner
Declare Function Test Lib "NomDeLaDLL.DLL" () As String
Sub Main()
MsgBox Test()
End Sub
DLL PB
Code : Tout sélectionner
Macro ProcedureReturnSysString(VarName)
! mov eax, [p.v_#VarName]
! mov [esp + 20], eax
ProcedureReturn
EndMacro
Global Hnd.I
ProcedureDLL.I TestB()
Hnd = SysAllocStringByteLen_("MESSAGE DE LA DLL OK", 20)
ProcedureReturnSysStringGlobal(Hnd)
EndProcedure
Cette procédure PB est censée retourner le message "MESSAGE DE LA DLL OK" comme convenu, mais permet aussi de récupérer le handle de la chaîne sous PB. Il est stocké dans Hnd. Grâce à cette variable, nous allons pouvoir utiliser la commande de libération de la mémoire de chaîne et donc gérer cette mémoire pour éviter de planter PB. Mais il faut vérifier si elle plante. La macro ProcedureReturnSysStringGlobal() devrait normalement bien remplacer le fameux ProcedureReturn Hnd qui te donnait des nombres bidons au lieu de la chaîne.
(2)>> J'attends donc ta réponse si ce code marche, crashe ou donne aussi des résultats bidon.
En attendant, je suis vraiment désolé mais j'ai l'icône Low Battery qui s'affiche au coin de l'oeil. Je ne vais pas tarder à rejoindre les bras de Morphée. Je te dis donc à demain.
Ollivier
PS: Si le fait de te demander deux choses à la fois te gène, tu peux bien sûr me prévenir pour que je ralentisse.
Publié : jeu. 13/août/2009 0:10
par NY152
J'ai une erreur :
Code : Tout sélectionner
PureBasic.asm[138]:
MP6
PureBasic.asm[118] MP6 [7]:
mov eax, [p.v_Hnd]
error: undefined symbol 'p.v_Hnd'.
Pour la fonction Test elle fonctionnait sans boucle, pour la fonction que tu m'a donné ben impossible à tester du coup vue que j'ai cette erreur à la compilation.
Pour la méthode de travail, elle me convient très bien
EDIT
J'ai oublié de mettre le ccode de la boucle
J'ai testé avec ça :
Code : Tout sélectionner
MsgBox "test"
Dim i As Integer
i = 0
Do While i <> 1000
i = i + 1
Test
Loop
MsgBox "test"
puis avec ça :
Code : Tout sélectionner
MsgBox "test"
Dim i As Integer
For i = 0 To 10000
Test
Next i
MsgBox "test"
Publié : jeu. 13/août/2009 11:37
par Ollivier
Aïe aïe aïe, si je ne te poste pas la bonne macro, tu ne risques pas de bien tester!
En fait j'ai enlevé le petit "p." dans mov eax. p comme procedure. Au passage, cette macro tente d'imiter exactement ce que fait
Procedure SysAllocStringByteLen_(Etc...)
C'est-à-dire qu'elle charge la pile de la valeur de retour puisque la pile est utilisée par VB pour lire la valeur de retour.
Code : Tout sélectionner
Macro ProcedureReturnSysStringGlobal(VarName)
! mov eax, [v_#VarName]
! mov [esp + 20], eax
ProcedureReturn
EndMacro
Global Hnd.I
ProcedureDLL.I TestB()
Hnd = SysAllocStringByteLen_("MESSAGE DE LA DLL OK", 20)
ProcedureReturnSysStringGlobal(Hnd)
EndProcedure
Ensuite, pour tes codes en VB, je te remercie. ça me donne une idée de la syntaxe vb. Je suis étonné que tu n'aies pas besoin de mettre de paire de parenthèses après Test. C'est sûrement une particularité VB.
Est-ce que la boucle de 1000 (mille) itérations plante?
Publié : jeu. 13/août/2009 12:19
par Ollivier
En fait, il faudrait réduire le nombre (1000) pour voir quand ça ne plante plus. Si, avec 100, ça ne plante plus, ça te permet de surveiller la différence de mémoire dans le gestionnaire de tâches.
Le modèle de la DLL devra être le suivant:
Code : Tout sélectionner
Macro ProcedureReturnSysStringGlobal(VarName) ; Macro pour renseigner VB6 à propos de l'adresse de la chaîne de retour. (à vérifier dans le test précédent)
! mov eax, [v_#VarName]
! mov [esp + 20], eax
ProcedureReturn
EndMacro
Global SPtr.I ; (String pointor) Pointeur de la chaîne accessible par VB
ProcedureDLL Init()
SPtr = SysAllocStringByteLen_(" ", 1) ; (1) Allocation de la chaîne
EndProcedure
ProcedureDLL Diverse() ; Une des procédures (toutes les procédures retournant une chaîne à VB6 devront agir ainsi)
... CodePB ...
SPtr = ReAllocString_(SPtr, "Nouvelle chaîne") ; (2) Modification de la chaîne
... CodePB ...
ProcedureReturnSysStringGlobal(SPtr) ; Export de la chaîne vers VB6
EndProcedure
ProcedureDLL.I Close()
SysFreeString_(SPtr) ; (3) Libération de la chaîne
EndProcedure
(J'ai remplacé Hnd par SPtr mais ça n'est qu'un détail)
ça commence à te parler ?!? Car ce sera un code de ce type pour le prochain test à faire avec une boucle de 1000 ou + dans VB pour vérifier que ça ne crashe plus.
Doc MSDN:
Allocation
Modification
Libération
Publié : jeu. 13/août/2009 12:55
par Ollivier
Test suivant (Test du jeudi de l'angoisse)
Sous VB6:
Code : Tout sélectionner
Declare Function InitLib Lib "MaLib.DLL" () As Integer
Declare Function Test Lib "MaLib.DLL" () As String
Declare Function TestB Lib "MaLib.DLL" () As String
Declare Function CloseLib Lib "MaLib.DLL" () As Integer
Sub Main()
MsgBox "Début de test A"
Dim i As Integer
Dim s As String
InitLib()
For i = 0 To 1000
s = Test()
Next i
CloseLib()
MsgBox "Fin de test A et début de test B"
For i = 0 To 1000
s = TestB()
Next i
MsgBox "Fin de test B"
End Sub
DLL PB:
Code : Tout sélectionner
Macro ProcedureReturnSysStringGlobal(VarName)
! mov eax, [v_#VarName]
! mov [esp + 20], eax
ProcedureReturn
EndMacro
Global SPtr.I
ProcedureDLL.I InitLib()
SPtr = SysAllocStringByteLen_(" ", 1)
ProcedureReturn
EndProcedure
ProcedureDLL.I Test()
SPtr = ReAllocString_(SPtr, "Nouvelle chaîne")
ProcedureReturnSysStringGlobal(SPtr)
EndProcedure
ProcedureDLL.I TestB()
ProcedureReturn SysAllocStringByteLen_(SPtr, "On reteste l'ancien pour être sûr qu'il crashe...", 49)
EndProcedure
ProcedureDLL.I CloseLib()
SysFreeString_(SPtr)
ProcedureReturn
EndProcedure
Publié : jeu. 13/août/2009 13:45
par NY152
Ollivier a écrit :Aïe aïe aïe, si je ne te poste pas la bonne macro, tu ne risques pas de bien tester!
En fait j'ai enlevé le petit "p." dans mov eax. p comme procedure. Au passage, cette macro tente d'imiter exactement ce que fait
Procedure SysAllocStringByteLen_(Etc...)
C'est-à-dire qu'elle charge la pile de la valeur de retour puisque la pile est utilisée par VB pour lire la valeur de retour.
Code : Tout sélectionner
Macro ProcedureReturnSysStringGlobal(VarName)
! mov eax, [v_#VarName]
! mov [esp + 20], eax
ProcedureReturn
EndMacro
Global Hnd.I
ProcedureDLL.I TestB()
Hnd = SysAllocStringByteLen_("MESSAGE DE LA DLL OK", 20)
ProcedureReturnSysStringGlobal(Hnd)
EndProcedure
Ensuite, pour tes codes en VB, je te remercie. ça me donne une idée de la syntaxe vb. Je suis étonné que tu n'aies pas besoin de mettre de paire de parenthèses après Test. C'est sûrement une particularité VB.
Est-ce que la boucle de 1000 (mille) itérations plante?
En fait ça ne change rien, même une boucle de 2 plante. J'avoue ne pas comprendre du tout

Publié : jeu. 13/août/2009 13:52
par NY152
Ollivier a écrit :Test suivant (Test du jeudi de l'angoisse)
Sous VB6:
Code : Tout sélectionner
Declare Function InitLib Lib "MaLib.DLL" () As Integer
Declare Function Test Lib "MaLib.DLL" () As String
Declare Function TestB Lib "MaLib.DLL" () As String
Declare Function CloseLib Lib "MaLib.DLL" () As Integer
Sub Main()
MsgBox "Début de test A"
Dim i As Integer
Dim s As String
InitLib()
For i = 0 To 1000
s = Test()
Next i
CloseLib()
MsgBox "Fin de test A et début de test B"
For i = 0 To 1000
s = TestB()
Next i
MsgBox "Fin de test B"
End Sub
DLL PB:
Code : Tout sélectionner
Macro ProcedureReturnSysStringGlobal(VarName)
! mov eax, [v_#VarName]
! mov [esp + 20], eax
ProcedureReturn
EndMacro
Global SPtr.I
ProcedureDLL.I InitLib()
SPtr = SysAllocStringByteLen_(" ", 1)
ProcedureReturn
EndProcedure
ProcedureDLL.I Test()
SPtr = ReAllocString_(SPtr, "Nouvelle chaîne")
ProcedureReturnSysStringGlobal(SPtr)
EndProcedure
ProcedureDLL.I TestB()
ProcedureReturn SysAllocStringByteLen_(SPtr, "On reteste l'ancien pour être sûr qu'il crashe...", 49)
EndProcedure
ProcedureDLL.I CloseLib()
SysFreeString_(SPtr)
ProcedureReturn
EndProcedure
ReAllocString_ n'existe pas. Je pars du principe qu'il s'agit de SysAllocStringByteLen_ ?
EDIT : J'ai mis SysAllocStringByteLen_ et j'ai corrigé la fonction TestB qui contenait une erreur (trop de paramètres). VB plante en beauté.
Publié : jeu. 13/août/2009 14:33
par Ollivier
Je vais trop vite! Et comme je mélange les codes VB et PB dans mon éditeur, je ne vérifie plus mon code PB et donc je fais des erreurs bêtes en plus de ça.
Donc teste ceci, ça teste la macro qui s'occupe de charger la pile de l'info de chaîne pour VB.
Code VB6:
Code : Tout sélectionner
Declare Function Test Lib "NomQueJeNeConnaisPas.DLL" () As String
Sub Main()
MsgBox Test()
End Sub
DLL PB:
Code : Tout sélectionner
Macro ProcedureReturnSysStringGlobal(VarName)
! mov eax, [v_#VarName]
! mov [esp + 20], eax
ProcedureReturn
EndMacro
Global SPtr.I
ProcedureDLL.I Test()
SPtr = SysAllocStringByteLen_("MESSAGE DE LA DLL OK", 20)
ProcedureReturnSysStringGlobal(SPtr)
EndProcedure
ça marche sous VB6?
Publié : jeu. 13/août/2009 15:29
par NY152
Ça plante ...
Publié : jeu. 13/août/2009 16:17
par NY152
Je me suis amusé à faire 3 fonctions :
Code : Tout sélectionner
ProcedureDLL.I RetourneRepertoire(Chemin$)
Protected Repertoire.S
Repertoire=GetPathPart(Chemin$)
ProcedureReturn SysAllocStringByteLen_(Repertoire,Len(Repertoire))
EndProcedure
ProcedureDLL.I RetourneFichier(Chemin$)
Protected Fichier.S
Fichier=GetFilePart(Chemin$)
ProcedureReturn SysAllocStringByteLen_(Fichier,Len(Fichier))
EndProcedure
ProcedureDLL.I RetourneExtension(Chemin$)
Protected Extension.S
Extension=GetExtensionPart(Chemin$)
ProcedureReturn SysAllocStringByteLen_(Extension,Len(Extension))
EndProcedure
J'ai fais une boucle sur le dossier Windows, ça n'a jamais planté.
Je commence à me demander si les fonctions de Winamp ne sont pas trop lente dans le sens "libération" du terme.
EDIT :
On m'a dit que les DLL Windows devait avoir ce code en plus du reste :
Code : Tout sélectionner
ProcedureDLL AttachProcess(Instance)
EndProcedure
ProcedureDLL DetachProcess(Instance)
EndProcedure
ProcedureDLL AttachThread(Instance)
EndProcedure
ProcedureDLL DetachThread(Instance)
EndProcedure
Je pense qu'elle servent à déclarer/libérer tout le toutim mais sans vraiment avoir creusé la chose, je m'abstiendrais de dire une bêtise lol
Publié : jeu. 13/août/2009 18:24
par Ollivier
Le problème c'est que si le nombre de fichier dépasse les 1000 (tu disais que ça crashait aussi à 1000), ben ça va planter.
Il faut donc contrôler cette macro qui permet de "détâcher" la fonction API du procedurereturn et stocker ainsi le pointeur retourné par la fonction API dans une variable globale, afin de pouvoir modifier et libérer l'espace pour chaîne identifié par cette variable
Code : Tout sélectionner
Macro ProcedureReturnSysStringGlobal(VarName)
! mov eax, [v_#VarName]
! mov [esp + 20], eax
ProcedureReturn
EndMacro
Remplace +20 par +16, s'il te plaît.
Publié : jeu. 13/août/2009 20:12
par NY152
La fonction que tu me demandais de tester crashe au bout de ... 2 pas 1000.
Publié : jeu. 13/août/2009 21:01
par NY152
ta dernière macro semble fonctionner je vais pousser les tests pour voir ^^
EDIT Fausse joie ça plante
