Page 1 sur 1

Ce matin interro sur la mémoire et les tableaux d'une DLL

Publié : mar. 04/août/2009 9:53
par Kwai chang caine
Bonjour la famille :D

Bon je ne sais pas si vous avez suivi les episodes precedents de "KCC et le tableau magique".
C'est l'histoire d'un tableau que j'avais et "Pffffoouuuuf !!" il disparait

A coté de KCC .....COPPPERFIELD c'est un cornichon :D

Enfin sinon, c'est pas grave.

J'ai donc voulu passer des tableaux de strings dynamiques d'une procedure de DLL à un EXE.
Plein d'amis, m'ont aidé et j'ai donc obtenu plusieurs methodes.

Kcc il a été obligé de choisir une, qui lui parait le plus adapté à son niveau de connaissance.
Et ..."c'est encore un militaire qui gagne une tringle a rideau" (Coluche) :D

Donc, je vais utiliser la super methode de mon ami Cpl, car deja je l'ai comprise, apres qu'il me l'ai expliqué sur trois jours.
Et comme il le dit, elle est universelle, et elle apprend a gerer la memoire.
Enfin bref, .....je la sent :D

Mais voila, pendant mes perigrinations, XOMBIE m'a dit que je ne gerait pas correctement la memoire, quand j'ai presenté le code de Cpl modifié sauce KCC :oops:

J'ai cherché a faire comme il dit, mais y'a des << et des >> des SizeOff, enfin bref, un chouilla , pour ne pas dire un BIG chouilla au dessus des connaissances de KCC :oops:

Donc ma question est....est ce que mon code a vraiment besoin d'etre peaufiné au niveau de la mémoire (car il marche comme ça, mais bon ....)

Voici mon code

Code : Tout sélectionner

; http://www.purebasic.fr/french/viewtopic.php?p=101521#101521

ProcedureDLL.l CreateArray(Parametre)
    
 Static Passage, xx, *PointerString 
 Passage + 1 
    
 If Passage = 1 
  *PointerString = AllocateMemory(100000 * 4); Tableau de pointeur 
  If Parametre = 1 
   Lettre.s = "a" 
  Else 
   Lettre.s = "c" 
  EndIf 
 Else 
  If Parametre = 2 
   Lettre.s = "b" 
  Else 
   Lettre.s = "d" 
  EndIf 
 EndIf 
  
 For x = 1 To 4 
  xx + 1 
  LenString = Len(RSet("", xx, Lettre)) 
  *String = AllocateMemory(LenString * 4) 
  PokeS(*String, RSet("", xx, Lettre)) 
  PokeI(*PointerString + (xx * 4), *String) 
 Next 
  
 If Passage = 1 
  CreateArray(Parametre) 
  ReAllocateMemory(*PointerString, (xx * 4) + 4) 
  Passage = 0 
  xx = 0 
 EndIf 
  
 PokeI(*PointerString, #Null) 
 ProcedureReturn *PointerString 
    
EndProcedure 

Dim ArrayA.s(0) 
ArrayA() = CreateArray(1) 
  
Dim ArrayB.s(0)  
ArrayB() = CreateArray(2) 

For i = 1 To (MemorySize(ArrayA()) / 4) - 1 
 Debug "Premier essai = " + ArrayA(i) 
Next 

For i = 1 To (MemorySize(ArrayB()) / 4) - 1  
 Debug "Second essai = " + ArrayB(i) 
Next
Et voici la remarque de XOMBIE
Xombie a écrit :Kwai,

Change this part in your program.

Code : Tout sélectionner

Dim ArrayA.s(10) 
Debug "Old Array address: "+Str(@ArrayA())
Debug "Old array item count (using ArraySize): "+Str(ArraySize(ArrayA()))
Debug "Old array item count (using peek): "+Str(PeekL(@ArrayA() - 8) )
ArrayA() = CreateArray() 
Debug "New 'Array' address: "+Str(@ArrayA())
Debug "New array item count (using peek): "+Str(PeekL(@ArrayA() - 8) )
Debug "New array item count (using memory size): "+Str(MemorySize(@ArrayA()) >> 2)
And notice what happens. You're not creating an array. You're creating a memory block.

Now the question becomes - do you have to have an array or can you use a block of memory that thinks it's an array?

Maybe you should rethink what you're doing. Sometimes in programming it's easy to get stuck thinking you *have to* do something one way.

First, I think this line is in error:

Code : Tout sélectionner

ReAllocateMemory(*PointerString, (xx * 4) + 1) 
As it should be adding one to xx. You want one more item, right? If you add it after you multiple times 4 then you'll get 41 bytes of memory rather than 44 and that can't hold 11 items.

Use:

Code : Tout sélectionner

ReAllocateMemory(*PointerString, ((xx + 1) << 2)) 
The '<< 2' is a little faster as a bit shift as well.

Also, I don't know what the extra 'CreateArray()' call does in your CreateArray() procedure.

Also, you're still only allocating one memory address and assigning it to your two different 'arrays'.

Well, in fact you have quite a few errors in pointers and such so I cleaned up your code for what it looked like you were doing. Especially since it seemed like you were trying to enable it for 32 and 64 bit operations. Try the following code...

Code : Tout sélectionner

Procedure FreePBString(*Address) 
   ; Procedure and method of removing structure strings from memory from freak @ http://www.purebasic.fr/english/viewtopic.php?t=23099&start=0
   Protected String.String
   ;
   PokeL(@String, *Address)
   ;
EndProcedure 
ProcedureDLL.l CreateArray(Which.i) 
   ;
   Define.i xx, *PointerString 
   ;
   *PointerString = AllocateMemory(100000 << ((SizeOf(Integer) >> 2) + 1)); Tableau de pointeur 
   ;
   If Which = 1 
      Lettre.s = "a" 
   Else 
      Lettre.s = "b" 
   EndIf 
   ;
   For x = 1 To 5 
      LenString = Len(RSet("", x, Lettre)) 
      *String = AllocateMemory((LenString << (SizeOf(Character) - 1)) + SizeOf(Character)) 
      PokeS(*String, RSet("", x, Lettre)) 
      PokeI(*PointerString + ((x - 1) << ((SizeOf(Integer) >> 2) + 1)), *String); ((x - 1) << (SizeOf(Integer) >> 2)), *String) 
      xx + 1 
   Next 
   ;
   *PointerString = ReAllocateMemory(*PointerString, xx << ((SizeOf(Integer) >> 2) + 1))
   ;
   ProcedureReturn *PointerString 
   ;
EndProcedure 

*MemoryA = CreateArray(1)

*MemoryB = CreateArray(2)

SizeA.i = MemorySize(*MemoryA) >> 2
Debug SizeA
SizeB.i = MemorySize(*MemoryB) >> 2
Debug SizeB

For i = 1 To SizeA
   Debug "Premier essai = " + PeekS(PeekI(*MemoryA + ((i - 1) << ((SizeOf(Integer) >> 2) + 1))))
Next 
  
For i = 1 To SizeB
   Debug "Premier essai = " + PeekS(PeekI(*MemoryB + ((i - 1) << ((SizeOf(Integer) >> 2) + 1))))
Next 

Debug "Free A..."
For i = 1 To SizeA
   FreePBString(PeekI(*MemoryA + ((i - 1) << ((SizeOf(Integer) >> 2) + 1))))
Next 
  
Debug "Free B..."
For i = 1 To SizeB
   FreePBString(PeekI(*MemoryB + ((i - 1) << ((SizeOf(Integer) >> 2) + 1))))
Next 
  
FreeMemory(*MemoryA)

FreeMemory(*MemoryB)
Je vous remercie de votre aide
Bonne journée

Publié : mer. 05/août/2009 12:33
par Kwai chang caine
Bon personne ne peux me dire, dans tous ceux qui ont toujours les mains dans le camboui, si ma gestion de la memoire est bonne ou bien si il faut que je corrige comme le dit XOMBIE :cry:

Bon voici la derniere mouture......
Ca marche enfin, mais ai-je bien géré le caractere null de fin de tableau de pointeur :roll:
Cette fois j'arrive a detecter la fin du tableau...mais est ce un coup de chance ???
KCC y voudrais en finir avec ce cauchemar de tableau et de DLL :?
Et surtout etre sur avant de tout poser dans sa DLL :roll:

Merci de votre aide

Code : Tout sélectionner

ProcedureDLL RechercheElement(StartDirectory.s, pattern.s, Recursive=1)

 Static strFiles.s 
 Static ct1, Passage ,*PointerString
 
 If Passage = 0
  *PointerString = AllocateMemory(100000 * 4); Tableau de pointeur 
 EndIf
 
 mDir = ExamineDirectory(#PB_Any, StartDirectory, "*.*")
   
 If mDir
 
  While NextDirectoryEntry(mDir) 
    
   If DirectoryEntryType(mDir) = #PB_DirectoryEntry_File 
    
    Directory$ = StartDirectory 
    FileName.s = DirectoryEntryName(mDir) 
    
    If FindString(FileName,pattern, 1) 
     LenString = Len(FileName)
     *String = AllocateMemory(LenString * 4)
     PokeS(*String, FileName)
     PokeI(*PointerString + (Ct1 * 4), *String)
     Ct1 + 1
    EndIf
    
   Else 
   
    tdir$ = DirectoryEntryName(mDir) 
   
    If tdir$ <> "." And tdir$ <> ".." 
     
     If Recursive = 1 
      Passage + 1
      RechercheElement(StartDirectory + "\" + tdir$, pattern) 
      Passage - 1
     EndIf 
     
    EndIf 
   
   EndIf 
  
  Wend
  
  FinishDirectory(mDir)
  
 EndIf 
 
 If Passage = 0
  PokeI(*PointerString + (Ct1 * 4), #Null)
  ReAllocateMemory(*PointerString, (Ct1 + 1) * 4)
  Ct1 = 0
 EndIf 
 
 ProcedureReturn *PointerString

EndProcedure

Dim TabloPB.s(0)
TabloPB() = RechercheElement("c:\",".pb", 1)

Dim TabloVB.s(0)
TabloVB() = RechercheElement("c:\",".vb", 1)

For i = 1 To 100

 If @TabloPB(i) <> 0
  Debug TabloPB(i)
 Else
  Break 
 EndIf 
 
Next

For i = 1 To 100

 If @TabloVB(i) <> 0
  Debug TabloVB(i)
 Else
  Break 
 EndIf 
 
Next