Page 3 sur 4

Re: Envoyer une chaine en référence

Publié : sam. 22/mars/2014 17:40
par nico
Oui Dobro a raison.

Ce n'est pas que les pointeurs ne sont pas typés, c'est qu'ils n'acceptent qu'un seul type qui est Integer (.i) (enfin depuis que la version x64 existe)

Avant on pouvait faire *pointer.a ou *pointer.w et le compilateur ne bronchait pas mais comme le compilateur voyait que c'était un pointeur, il était correctement interprété comme un .i ou .l avant la version x64.

Je parlais d'une exception plus haut, il s'agit justement des Strings car lorsqu'on place un @ devant un String, on a bien l'adresse de la mémoire contenant la chaîne de caractères; par contre dans une structure on obtient en fait l'adresse d'un pointeur vers l'adresse de la chaîne de caractères, voici un code illustrant ce propos:

Code : Tout sélectionner

Structure chaine
  Texte.s
EndStructure


Procedure.l ModifTexte (*Test.chaine)
  Debug PeekS(PeekI(*Test))
  *Test\Texte = *Test\Texte + " lolo"
EndProcedure


Test1.s = "lili"
Debug @Test1
; @Test1 --> ici on accède directement à l'adresse mémoire 
; de la chaine de caractère
*Pointer = @Test1 ; d'où la nécessité d'utilisé un pointeur dans cet exemple.
ModifTexte (@*Pointer)
Debug @Test1
Debug Test1


Test2.chaine\Texte = "popo"
Debug @Test2\Texte
; @Test2\Texte --> ici on accède à l'adresse d'une mémoire qui pointe 
; vers l' adresse mémoire de la chaine de caractère
; l'adresse mémoire de la chaine est donc PeekI(@Test2\Texte)
ModifTexte (@Test2)
Debug @Test2\Texte
Debug Test2\Texte

Re: Envoyer une chaine en référence

Publié : sam. 22/mars/2014 18:04
par falsam
■ Que dit l'aide ?
Un pointeur est une variable dite de type pointeur car son encombrement en mémoire sera lié à la capacité d'adressage mémoire du processeur.
Il en découle qu'affecter un type natif à un pointeur (*Pointeur.l, *Pointeur.b…) n'a aucun sens puisque l'encombrement mémoire d'un pointeur est imposé par celui d'une adresse et non par celui d'un type.
bombseb a écrit :j'ai pas eu ma réponse : J'ai pas saisi la différence entre .s et .String :oops:
String est une structure que tu peux associer à un pointeur pour lire le contenu d'une variable de type .s (String)

Code : Tout sélectionner

Texte$ = "Bonjour"
  *Texte = @Texte$ ;*Texte a pour valeur l'adresse où réside la chaîne de caractères en mémoire
  *Pointeur.String = @*Texte ; *Pointeur pointe sur *Texte
  Debug *Pointeur\s ; Lit la chaîne de caractères qui réside à l'adresse écrite en *Pointeur (c-a-d @Texte$)
La structure String est trés simple

Code : Tout sélectionner

Structure String
    s.s
EndStructure

Re: Envoyer une chaine en référence

Publié : sam. 22/mars/2014 18:10
par bombseb
hum...mouais, il faut que je digère tous ca :o

Re: Envoyer une chaine en référence

Publié : sam. 22/mars/2014 18:15
par bombseb
Mais alors si .String est une structure, ce code devrais fonctionner non ?

Code : Tout sélectionner

Procedure.a Dummy(*Buffer.String)
  *Buffer\s = "test"
EndProcedure

Buffer.s="titi"
Dummy(@Buffer)
Debug Buffer

Re: Envoyer une chaine en référence

Publié : sam. 22/mars/2014 18:26
par falsam
Tu as mal lu ce que j'ai écrit
String est une structure que tu peux associer à un pointeur pour lire le contenu d'une variable de type .s (String)

Je ne comprends pas pourquoi tu tiens tant à mettre à jour le contenu d'une variable avec cette méthode ?

Re: Envoyer une chaine en référence

Publié : sam. 22/mars/2014 18:29
par bombseb
Non mais je cherche juste à comprendre :wink:
de toute façon j'ai utilisé la méthode du PokeS

Re: Envoyer une chaine en référence

Publié : sam. 22/mars/2014 19:02
par nico
Si tu modifies mais que tu n'as pas l'intention d'augmenter le contenu de la variable, ça va; sinon utilise une variable String globale et terminé les problèmes.

Re: Envoyer une chaine en référence

Publié : sam. 22/mars/2014 19:11
par bombseb
Yes

Merci en tout ca :wink:

Re: Envoyer une chaine en référence

Publié : sam. 22/mars/2014 19:45
par Backup
nico a écrit :Si tu modifies mais que tu n'as pas l'intention d'augmenter le contenu de la variable, ça va; sinon utilise une variable String globale et terminé les problèmes.

si on peut , grace a movememory() :)

Code : Tout sélectionner



Declare.a incLettre (lettre)

calldebugger
toto$ = "A" +space(1024) ; ajout de place pour pouvoir remplir uterieurement.... 
debug "avant l'appel de la procedure toto ="+toto$
incLettre (@toto$)
; comme le debugger est limité en longueur de chaine , je vais utiliser message requester
;debug "Apres l'appel de la procedure toto="+toto$
MessageRequester("toto", toto$)

Procedure.a incLettre (lettre)
	
	; Invalid memory access
	Debug  "adresse de Toto ="+str(lettre)
	Debug "contenue de Toto= "+peeks(lettre)
	; on va changer le contenu de toto
	t$="rien ne sert de courir , il faut partir a point , je pourrai ainsi ajouter la longueur que je veux, parcequ'il n'y a pas de raison, que ça bloque , j'ai prevu de la place pour 1024 caracteres de plus ... "
	
	MoveMemory(@t$, lettre, len(t$)) ; marche car on a prevu de la place au depart !! 
; du coup on peut aussi utiliser CopyMemory()
; CopyMemory(@t$, lettre, len(t$)) ;marche car j'ai prevu de la place des le debut !! 
	
EndProcedure


; Epb


Re: Envoyer une chaine en référence

Publié : sam. 22/mars/2014 20:21
par nico
Si tu fais un MoveMemory, le PokeS ne sert à rien du coup!

Qu'est ce qui se passe avec un MoveMemory ? , il écrase ce qu'il y avait avant, non ?

Re: Envoyer une chaine en référence

Publié : sam. 22/mars/2014 23:31
par Backup
............ viré car explications foireuse ! :oops:

Re: Envoyer une chaine en référence

Publié : dim. 23/mars/2014 0:46
par nico
ben tu l'a commenter pour voir ?
Oui, ça marche; j'ai regardé encore une fois, d'un coté tu déplaces et ensuite tu refais une copie (qui est injustifiée et inutile de ce que j'en comprend)

La différence entre copymemory et movememory, c'est qu'avec ce dernier la mémoire source est libérée.

La segmentation de la mémoire; c'est la séparation en bloc du programme, je ne pense pas qu'on puisse parler de segmentation pour une variable mais bon c'est trop pointu pour moi.

La question, c'est y a t'il une réservation plus conséquente? un peu comme sur le disque avec les secteurs, franchement, j'en sais rien.

Je serais plutôt partant pour manipuler une chaîne de caractère à longueur déterminée, ça me parait plus sûr.

Je suis quand même dans le doute, si je déclare une variable globale, genre toto.s et que je m'amuse à changer son contenu des milliers de fois dans le programme, je n'ai pas souvenir d'avoir constaté ou d'avoir lu que son adresse mémoire pouvait changer. Ce qui pourrait signifier que peut être Purebasic réserverait un espace minimum conséquent pour cette variable. Gros point d'interrogation.

Re: Envoyer une chaine en référence

Publié : dim. 23/mars/2014 2:16
par Backup
nico a écrit :
ben tu l'a commenter pour voir ?
Oui, ça marche;
haaa! mais pas chez moi !! d'ou le pokes() ....
sans le pokes , j'ai un plantage (je l'ai pourtant ecris .... ) 8O

pourquoi ça marche chez toi, et pas chez moi ??

je suis en Version 5.22 x86 .....


je parle de segment de mémoire, car une Variable, représente bien un 'petit' segment de la ram dans tout les cas ... :)
avec un debut (l'adresse de debut de la variable ----> '@') et une longueur (.l,.i,.c .s ...etc )



je ne comprends pas pourquoi chez toi sans le Pokes() ça fonctionne , alors que j'ai un plantage en sortie de procedure sur le Endprocedure ..... :roll:



en fait j'arrive a le faire marcher sans le pokes() si je fait :

MoveMemory(@t$, lettre-4, len(t$)) :roll:

ça sent le bug sur la version 5.22

j'ai signalé sur le forum anglais .... wait and see :)

Re: Envoyer une chaine en référence

Publié : dim. 23/mars/2014 3:04
par majikeyric
Je pense que ce plantage est aléatoire, en fonction du contenu de la mémoire. Chez moi, des fois ça plante ou pas.

Movememory() n'est pas censé faire une allocation mémoire. Il prend les octets bruts et les copie à l'adresse indiquée. Après si tu écris dans une zone reservée bein ça plante.

Les 2 zones peuvent se chevauchent c'est à dire:

Par exemple, tu copie avec MoveMemory() les octets de l'adresse 0 à 10 à l'adresse 5. C'est comme si tu les déplacer de 5 octets d'ou le "Move" (les zones se chevauchent).

Avec un CopyMemory tu ne pourrais pas le faire, si tu copie l'octet 0 en 5, ensuite quand tu arrive à l'octet 5 pour le copier en 10, sa valeur ne correspond pas à l'octet 5 initial mais à l'octet 0 copié.

Code : Tout sélectionner

0|----------------------------------|10
            
                      5|----------------------------------|15
ça n'a rien à voir avec dés réallocations mémoires pour des chaines de caratères.

Le Movememory() doit doit copier les octets par décrémentation des adresses je pense (en commençant par la fin) ou dans une mémoire tampon.


Et quand tu spécifies len(t$) pour le nombre d'octets à copier, c'est n'est pas forcément la longueur de la chaine en octets (selon ascii/unicode)....

Re: Envoyer une chaine en référence

Publié : dim. 23/mars/2014 10:21
par Backup
oui , donc, mon code est dangereux pour la Ram !

seule solution prevoir en amont une place suffisante dans la variable qui va recevoir

j'ai changé le code dans ce sens :)

j'ajoute space(1024) pour ajouter la place pour 1024 caracteres ...




ps: lorsque tu compile en unicode, de toute façon tout les caracteres (meme ceux ajouté par Space() ) prennent 2 octets ... donc c'est bon :)