Envoyer une chaine en référence

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Re: Envoyer une chaine en référence

Message 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
Avatar de l’utilisateur
falsam
Messages : 7324
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Envoyer une chaine en référence

Message 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
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Re: Envoyer une chaine en référence

Message par bombseb »

hum...mouais, il faut que je digère tous ca :o
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Re: Envoyer une chaine en référence

Message 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
Avatar de l’utilisateur
falsam
Messages : 7324
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Envoyer une chaine en référence

Message 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 ?
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Re: Envoyer une chaine en référence

Message par bombseb »

Non mais je cherche juste à comprendre :wink:
de toute façon j'ai utilisé la méthode du PokeS
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Re: Envoyer une chaine en référence

Message 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.
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Re: Envoyer une chaine en référence

Message par bombseb »

Yes

Merci en tout ca :wink:
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: Envoyer une chaine en référence

Message 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

Dernière modification par Backup le dim. 23/mars/2014 10:39, modifié 3 fois.
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Re: Envoyer une chaine en référence

Message 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 ?
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: Envoyer une chaine en référence

Message par Backup »

............ viré car explications foireuse ! :oops:
Dernière modification par Backup le dim. 23/mars/2014 10:23, modifié 1 fois.
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Re: Envoyer une chaine en référence

Message 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.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: Envoyer une chaine en référence

Message 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 :)
Avatar de l’utilisateur
majikeyric
Messages : 602
Inscription : dim. 08/déc./2013 23:19
Contact :

Re: Envoyer une chaine en référence

Message 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)....
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: Envoyer une chaine en référence

Message 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 :)
Répondre