Page 1 sur 2

AppendMemory

Publié : mar. 14/nov./2006 10:19
par Progi1984
Voilà, mon pb est là :

J'ai une zone mémoire (AllocateMemory et PokeX pour lui attribuer du contenu).

Mais je souhaiterais ajouter qqch à la fin de la zone mémoire précédement crée.

Quelqu'un aurait un exemple pour me montrer comment faire, SVP ?

Publié : mar. 14/nov./2006 13:44
par Guimauve
Dis donc est-ce que tu as regardé du coté de ReAllocateMemory() ?

Il semble que c'est possible d'agrandir une zone mémoire déja alloué. Et donc d'écrire plus d'information dans la zone mémoire.

Publié : mar. 14/nov./2006 14:34
par Progi1984
J'ai regardé... mais sans plus. Aurais tu un petit exemple ?

Publié : mar. 14/nov./2006 16:47
par brossden
Voila pour le petit exemple :

Code : Tout sélectionner

;Allocation de 1000 octets au pointeur *mem
*mem =AllocateMemory(1000)

;Attribution de la valeur 65 (caractère "A") de ces 1000 octets
For n=0 To 999
  PokeC(*mem+n,65)
Next
;Lecture de 20 octets à partir du 900 ième caractère de *mem

Debug PeekS(*mem+900,20)
Debug " "

;Réallocation de 1500 octets au pointeur *mem
*mem = ReAllocateMemory(*mem,1500)

;Attribution de la valeur 66 (caractère "B") de ces 500 octets supplémentaires
For n=1000 To 1500
  PokeC(*mem+n,66)
Next

;Lecture de 20 octets à partir du 990 ième caractère de *mem
Debug PeekS(*mem+990,20)

; Donc 10 "A" ( de 990 à 1000 ) suivit de 10 "B" (1000 à 1010)


Publié : mar. 14/nov./2006 16:57
par Progi1984
Merci, je viens de réaliser la fonction que je souhaitais :

Code : Tout sélectionner

Procedure AppendB(*Memory, Byte.b)
  ReAllocateMemory(*Memory,MemorySize(*Memory)+1)
  PokeB(*Memory+MemorySize(*Memory)-1, Byte)
EndProcedure
Procedure AppendC(*Memory, Character.c)
  CompilerIf #PB_Compiler_Unicode = 1
    ReAllocateMemory(*Memory,MemorySize(*Memory)+2)
    PokeC(*Memory+MemorySize(*Memory)-2, Character)
  CompilerElse
    ReAllocateMemory(*Memory,MemorySize(*Memory)+1)
    PokeC(*Memory+MemorySize(*Memory)-1, Character)
  CompilerEndIf
EndProcedure
Procedure AppendW(*Memory, Word.w)
  ReAllocateMemory(*Memory,MemorySize(*Memory)+2)
  PokeW(*Memory+MemorySize(*Memory)-2, Word)
EndProcedure
Procedure AppendL(*Memory, Long.l)
  ReAllocateMemory(*Memory,MemorySize(*Memory)+4)
  PokeL(*Memory+MemorySize(*Memory)-4, Long)
EndProcedure
Procedure AppendF(*Memory, Float.f)
  ReAllocateMemory(*Memory,MemorySize(*Memory)+4)
  PokeF(*Memory+MemorySize(*Memory)-4, Float)
EndProcedure
Procedure AppendQ(*Memory, Quad.q)
  ReAllocateMemory(*Memory,MemorySize(*Memory)+8)
  PokeQ(*Memory+MemorySize(*Memory)-8, Quad)
EndProcedure
Procedure AppendD(*Memory, Double.d)
  ReAllocateMemory(*Memory,MemorySize(*Memory)+8)
  PokeD(*Memory+MemorySize(*Memory)-8, Double)
EndProcedure
Procedure AppendS(*Memory, String.s)
  ReAllocateMemory(*Memory,MemorySize(*Memory)+Len(String))
  PokeS(*Memory+MemorySize(*Memory)-Len(String), String)
EndProcedure

*mem =AllocateMemory(10)

For n=0 To 9
  PokeC(*mem+n,65)
Next

Debug PeekS(*mem)
Debug "=========================="

For n=9 To 20
  AppendC(*mem, 66)
Next
Debug PeekS(*mem)


Publié : mar. 14/nov./2006 17:23
par Dr. Dri
ATTENTION !!!

ReAllocateMemory n'alloue pas forcément la mémoire à la même adresse !!

Code : Tout sélectionner

buffer = AllocateMemory(1024)

Debug Hex(buffer)

buffer = ReAllocateMemory(buffer, 1024*1024)

Debug Hex(buffer)
L'allocation peut même échouer

Code : Tout sélectionner

buffer = AllocateMemory(1024)

Debug Hex(buffer)

buffer = ReAllocateMemory(buffer, 1024*1024*1024)

Debug Hex(buffer)
Dri

Publié : mar. 14/nov./2006 20:08
par brossden
Oui.... C'est bien se casser la tête pour pas grand chose !! :roll:

Publié : mer. 15/nov./2006 9:12
par Progi1984
Alors comment pourrais je faire pour que mes Append<Type> fonctionne ?

Publié : mer. 15/nov./2006 15:12
par brossden
Solution 1

Allouer une grande taille mémoire à un pointeur, et redistribution des de cette mémoire en segments en fonction des mémoires plutot que de lui réaffecter un ou deux octets de plus !

Solution 2
Allouer autant de pointeur qu'il est necessaire.

Solution 3
Ecrire dans des mémores et si besoin, utiliser les adresses mémoires pour pouvoir jouer avec les peek et poke !!

et là ne s'arrêtent pas les solutions ....

Publié : mer. 15/nov./2006 15:47
par Progi1984
Disons que mon code fonctionne parfaitement, je l'ai testé hier soir dans un programme en essayant de le faire fonctionner un max et je n'ai aucun problème au final avec mon WriteData !

Publié : mer. 15/nov./2006 16:21
par brossden
On est jamais mieux servi que par soi même donc si ton algo te satisfait tout est parfait.
Tu n'est pas là pour nous faire plaisir, alors désolé si je t'ai énervé ce n'était pas mon intention ! !

Publié : mer. 15/nov./2006 16:22
par lionel_om
Je te conseille qd même un :

Code : Tout sélectionner

ProcedureReturn ReAllocateMemory(...)
Car y'a de grandes chances que l'adresse de la zone mémoire change dès que tu utilise plusieurs fois ton Append{?} sur une même zone mémoire :wink:

Publié : mer. 15/nov./2006 16:26
par Progi1984
@brossden : j'essaie juste d'avoir un code le plus sur possible ! Tu ne m'as pas du tout énervé :)

@All : Et si, je remplace mes procédures par des macros, est ce que cela ne serait pas sur genre

Code : Tout sélectionner

Procedure AppendB(*Memory, Byte.b)
  ReAllocateMemory(*Memory,MemorySize(*Memory)+1)
  PokeB(*Memory+MemorySize(*Memory)-1, Byte)
EndProcedure 
; remplacé par
Macro AppendB(Memory, Byte)
  ReAllocateMemory(Memory,MemorySize(Memory)+1)
  PokeB(Memory+MemorySize(Memory)-1, Byte)
EndMacro  

Publié : mer. 15/nov./2006 17:36
par brossden
Ecoute je vais te donner une solution mais j'ignore si j'ai bien pigé ton problème.

Je pars le principe qie tu veux empiler des valeurs les une derrières les autres et qui sont parfois chaine parfois quad word ou même bit.

Voici ma solution en admettant pour cet exemple que tu ne depasseras jamais une valeur de 1Mo

Code : Tout sélectionner

Global *Offset, *Point
*Offset = AllocateMemory(105000)
 *Point = *Offset
Debug *Offset
Procedure AppendS(Chaine.s)
  Lg=Len(Chaine)
  PokeS(*Offset,Chaine,Lg)
  *Offset+Lg
EndProcedure
Procedure AppendD(Valeur.d)
  PokeD(*Offset,Valeur)
  *Offset+8
EndProcedure
Procedure AppendQ(Valeur.q)
  PokeQ(*Offset,Valeur)
  *Offset+8
EndProcedure
Procedure AppendF(Valeur.f)
  PokeF(*Offset,Valeur)
  *Offset+4
EndProcedure
Procedure AppendL(Valeur.l)
  PokeL(*Offset,Valeur)
  *Offset+4
EndProcedure
Procedure AppendW(Valeur.w)
  PokeW(*Offset,Valeur)
  *Offset+2
EndProcedure
Procedure AppendCAsc(Valeur.c)
  PokeC(*Offset,Valeur)
  *Offset+2
EndProcedure
Procedure AppendUni(Valeur.c)
  PokeC(*Offset,Valeur)
  *Offset+1
EndProcedure
Procedure AppendB(Valeur.b)
  PokeB(*Offset,Valeur)
  *Offset+1
EndProcedure
;Ici ton code ..........
;par exemple :

for n=1 to 1000

 AppendS("Toto")
 AppendD($FF1234EF1B5C8D9E) 
 AppendQ($102158F5E6F51A75)
 AppendF(325.158)
 AppendL(6589988474887)
 AppendW(32000)
 AppendCAsc(255)
 AppendB(12)
Next
;............... etc...

;Pour finir

OpenFile(1,"c:\append1.txt")
WriteData(1,*Point,*Offset-*Point)
CloseFile(1)

Il faut savoir aussi que tu peux t'éviter d'ecrire toutes ces procedures

et écrire directement :

Code : Tout sélectionner

Global *Offset, *Point
*Offset = AllocateMemory(105000)
*Point = *Offset

For n=1 to 1000
 PokeS(*Offset,"Toto",4) : *Offset+4
 PokeD(*Offset,$FF1234EF1B5C8D9E) : *Offset+8
 PokeQ(*Offset,$102158F5E6F51A75) : *Offset+8
 PokeF(*Offset,325.158) : *Offset+4
 PokeL(*Offset,6589988474887) : *Offset+4
 PokeW(*Offset,32000) : *Offset+2
 PokeC(*Offset,255) : *Offset+1
 PokeB(*Offset,2) : *Offset+1
Next

OpenFile(1,"c:\append2.txt")
WriteData(1,*Point,*Offset-*Point)
CloseFile(1)
La deuxième solution à toutes mes voix cat le plus cours est souvent le plus rapide !

Test ces deux softs tu veras que le resultat est identique !

Publié : mer. 15/nov./2006 19:42
par Flype
@brossden

105000 c'est 105Ko, pas 1Mo.

c'est juste pour te charrier parce que ta facon de faire est selon moi la meilleure. enfin, au vu de ce que progi cherche à faire.

si les procédures de progi fonctionnent c'est de la chance. probablement parce qu'ici les quantités de mémoire allouées sont toutes petites.

progi alloue seulement 10 octets puis monte à 11, 12, 13, ... octets. peut etre que windows alloue direct un bloc de 1024 octets minimum en interne. du coup çà fonctionne mais c'est vraiment dangereux (enfin dangereux, c'est pas la fin du monde non plus).

la doc purebasic dit bien qu'il faut tenir compte du nouveau pointeur renvoyé par ReAllocateMemory().
Syntaxe

*MemoryID = ReAllocateMemory(*MemoireID, Taille)
Description

Alloue (si le paramètre *MemoroireID est 0) ou re-alloue une zone continue de mémoire de la Taille spécifiée (en octets). Si la zone de mémoire était déjà allouée, alors son ancien contenu est conservé. Si la quantité de mémoire demandée est disponible, *MemoryID contiendra l'adresse de début de la zone mémoire, ou 0 si la zone n'a pu être allouée (dans ce cas, l'ancienne zone mémoire est toujours valide).

Note: Toutes les zones mémoire créées sont automatiquement libérées à la fin du programme.
d'ailleurs il y a une petite coquille ici : *MemoroireID