Pointeur de chaines

Archive.
LavaLava
Messages : 173
Inscription : dim. 28/mars/2004 17:42
Localisation : Provence

Pointeur de chaines

Message par LavaLava »

Salut,
je ne suis pas sur que cela soit un bug mais cela m'enbête un peu...
En fait, je devais convertir du texte de 2 liste chainée.
Pour ne pas écrire 2 procédures identiques (à par le nom de la liste chainée), j'ai voulut utiliser un pointeur...
Mais apparament, si la variable n'a pas été accédé ou initialisé une fois, le pointeur ne fonctionne pas.

Voici un exemple simple pour mettre cela en évidence :

Code : Tout sélectionner

Procedure Change( *A$ )
*A$ = "Changed"
EndProcedure
Global B$
Change( @B$ )
Debug B$ ;  => ""
B$ = "Main"
Change( @B$ )
Debug B$ ; => "Canged"
End
Merci
Avatar de l’utilisateur
case
Messages : 1527
Inscription : lun. 10/sept./2007 11:13

Message par case »

cela me semble normal,
un simple global b$="" résout le problème

sans vouloir dire de bêtises, je suppose que faire un

global b$

définit simplement la variable comme étant globale, mais elle n'est pas initialisée et n'a donc pas d'adresse physique en mémoire.

un global b$="" l'initialise comme étant vide mais lui réserve tout de même une place en mémoire
ImageImage
LavaLava
Messages : 173
Inscription : dim. 28/mars/2004 17:42
Localisation : Provence

Message par LavaLava »

Salut,
Effectivement, je ne sais si c'est normal ou pas, mais les variables de type string n'ont pas d'adresse définite lors de leur déclaration par un global.
Par contre c'est le cas pour les variables numériques...

Code : Tout sélectionner

global A, A$
Debug @A
Debug @A$
Cependant, le fait d'initialiser les variables de type string n'a pas résolu mon problème ...

Exemple :

Code : Tout sélectionner

Procedure Change( *A$, *B$ ) 
*A$ = "Changed A" 
*B$ = "Changed B" 
EndProcedure 

Global AA$ = "", BB$ = ""
Change( @AA$ , @BB$) 
Debug AA$ + " " + BB$
Change( @AA$ , @BB$) 
Debug AA$ + " " + BB$
End
Chez moi, XP Sp3 et Pb 4.3, cela me génere une erreur "Invalid memory access" lors du second appel de la procédure ...
cha0s
Messages : 681
Inscription : sam. 05/mars/2005 16:09

Message par cha0s »

Code : Tout sélectionner

Procedure Change( *A, *B)
PokeS(*A, "Changed A")
PokeS(*B, "Changed B")
EndProcedure

Global AA$ = Space(Len("Changed A")+1), BB$ = Space(Len("Changed B")+1)
Change( @AA$ , @BB$)
Debug AA$ + " " + BB$
Change( @AA$ , @BB$)
Debug AA$ + " " + BB$
End 
si la mémoire n'est pas alloué tu risque de tomber sur une zone de mémoire interdite a ton programme car tu dépasse la taille initiale.
LavaLava
Messages : 173
Inscription : dim. 28/mars/2004 17:42
Localisation : Provence

Message par LavaLava »

Justement, mon but est de pouvoir modifier le contenue, et donc la longueur, d'une variable de type string en ne connaissant que son adresse !
Ce que je comprends pas c'est que, grâce à son adresse, je puisse lire le contenu de la variable mais pas le modifier...

Code : Tout sélectionner

Structure Test
  S$
EndStructure
Procedure Change( *V$ ) 
Debug "*V$=" + *V$
Debug "@*V$=" + Str( @*V$ )
*V$ = *V$ + *V$
EndProcedure 
Global AA.Test, BB.Test
AA\S$ = "ABCDEF"
Debug "Global @AA\S$=" + Str( @AA\S$ )
Change( @AA\S$ ) 
Change( @AA\S$ ) 
Debug "Result AA=" + AA\S$
Debug ""
BB\S$ = "IJKLMN"
Debug "Global @BB\S$=" + Str( @BB\S$ )
Change( @BB\S$ ) 
Change( @BB\S$ ) 
Debug "Result BB=" + BB\S$
cha0s
Messages : 681
Inscription : sam. 05/mars/2005 16:09

Message par cha0s »

c'est une question d'allocation mémoire quand tu initialise ta chaine elle prend telle taille en octet et cela ne changera pas si tu touche directement a l'adresse mémoire car le compilateur ne va pas allouer de la mémoire par l'opération du saint esprit.

Mais il y a une solution magique a cela c'est allocatememory(sizeof(char)*(longeur de chaine + 1)) a l'initialisation et reallocatememory(sizeof(char)*(longeur de la nouvelle chaine + 1))

Il ne faut pas oublier que l'adresse d'une chaine c'est un pointeur vers un pointeur (vous avez suivit ? :p) comme avec mysql pour les connaisseur on pointe vers le pointeur du résultat xD
LavaLava
Messages : 173
Inscription : dim. 28/mars/2004 17:42
Localisation : Provence

Message par LavaLava »

Salut,
C'est probalbement absurde au sens strict de la programmation, mais hormis le saint esprit, je m'attendais à ce que le PB gère la nouvelle taille de la mémoire ...
Car en fait, par un pointeur et une structure on peut lire et écrire dans l'espace mémoire allouée à une variable de type chaine, mais si on écrit un caractère de trop on plante !

A moins qu'il existe une syntaxe que j'ai pas encore trouvée ...
@+
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message par Ollivier »

Après un petit passage par l'option ASM, j'ai isolé la macro qui modifie une chaîne en fonction d'une autre.

L'instruction "LEA reg, [expr]" en ASM transfert le résultat de expr dans reg. Or expr c'est une expression créée lors de la compilation.

ça rejoint l'explication de ChaOs.

Code : Tout sélectionner

Macro InitStrCopy()
Define XXX.S
XXX + ""
EndMacro

Macro SetString(Cible, Source)
!  PUSH   dword [_PB_StringBasePosition]
!  MOV    edx,dword [v_#Source]
!  CALL  _SYS_CopyString@0
!  LEA    ecx,[v_#Cible] ; << *** Le souci est ici *** <<
!  POP    edx
!  CALL   SYS_AllocateString
EndMacro

   InitStrCopy()
   Define X.S
   Define Y.S = "Quartet"
   SetString(X, Y)

   Debug X
Répondre