Novembre 2024 | Lun | Mar | Mer | Jeu | Ven | Sam | Dim |
---|
| | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | | Calendrier |
|
|
| Bug avec a$=b$ | |
| | Auteur | Message |
---|
Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Bug avec a$=b$ Mer 3 Juin 2015 - 10:30 | |
| La ligne a$=b$ ne produit pas le résultat escompté. Contrairement à ce que l'on pourrait penser, les données ne sont pas copiées. Seul un pointeur sur les données de a$ est associé à la variable b$. Et cela conduit à des anomalies en utilisation par une DLL: - Code:
-
' demo du bug avec les variables string
dim a$, b$, c$ : ' définition de deux variables dim res% : ' pour appel des fonctions DLL
a$ = string$(25," ") : ' charger a$ par 25 espaces b$ = a$ : ' en faire une copie : ' ici, on devrait avoir deux chaînes distinctes, avec les mêmes données c$ = a$ + " " : ' ici, on a une nouvelle chaîne de 26 espaces
dll_on "KGF.dll" : ' ouvrir KGF.dll res% = dll_call1("KGFdllVersion",adr(a$)) message "a$="+a$ : ' variable chargée par la fonction DLL message "b$="+b$ : ' il ne devrait y avoir que des espaces ! : ' or, on a un contenu identique à a$ ! message "c$="+c$ : ' ici, on a bien une variable indépendante ' ceci prouve que la ligne "b$ = a$" est implémentée par un équivalant Delphi de: ' var ' a, b: string; ' begin ' a := StringOfChar(' ',25); ' b := a; ' Et l'on sait que dans ce cas, les données ne cont pas copiées. ' Seul un pointeur sur les données de a est copié.
end
En chargeant les 25 caractères de a$ par la fonction DLL, on a en apparence chargé également b$. Je pense que, lors d'une affectation de chaîne de caractères, il faut s'assurer que la copie des données est bien effectuée, dans tous les cas. La technique Delphi de ne copier que le pointeur en incrémentant le compteur d'utilisation n'est pas compatible avec un esprit "Basic". Une copie doit être une copie. | |
| | | jean_debord
Nombre de messages : 1266 Age : 70 Localisation : Limoges Date d'inscription : 21/09/2008
| Sujet: Re: Bug avec a$=b$ Jeu 4 Juin 2015 - 9:30 | |
| Par curiosité, j'ai essayé avec le compilateur. Voici le programme de test : - Code:
-
dim a$, b$
a$ = "abcd" b$ = a$
print a$ print b$
end
Et voici le code FreeBASIC généré (note : il faut le "capturer" avant que le compilateur l'efface !) - Code:
-
#include"MemoryModule.bi" #include"incfile.bi" IncFile(DLLdata,"panoramic.dll") #lang "fblite" option gosub #include once"windows.bi" dim shared _handl as HWND dim shared _library as HMEMORYMODULE _library = MemoryLoadLibrary(DLLdata) dim shared pc_init as sub stdcall _ (byval operand1 as handle) pc_init=MemoryGetProcAddress(_library,"pc_init") dim shared pc_close as sub pc_close=MemoryGetProcAddress(_library,"pc_close") DIM SHARED V_NUMBER_3D_OBJECTS AS DOUBLE DIM SHARED V_NUMBER_3D_TARGET AS DOUBLE DIM SHARED V_A AS STRING DIM SHARED V_B AS STRING dim shared pc_print_string as sub stdcall _ (byval P1 as string) pc_print_string=MemoryGetProcAddress(_library,"pc_print_string") declare function WinMain _ (byval _hInstance as HINSTANCE,_ byval _hPrevInstance as HINSTANCE,_ byval _szCmdLine as string,_ byval _iCmdShow as integer)as integer end WinMain(GetModuleHandle(null),null,Command(),SW_NORMAL) function WndProc _ (byval _hWnd as HWND,_ byval _wMsg as UINT,_ byval _wParam as WPARAM,_ byval _lParam as LPARAM)as LRESULT function=0 select case(_wMsg) case WM_CREATE exit function case WM_DESTROY pc_close() sleep 200 MemoryFreeLibrary(_library) PostQuitMessage(0) exit function end select function=DefWindowProc(_hWnd,_wMsg,_wParam,_lParam) end function function WinMain (byval _hInstance as HINSTANCE,_ byval _hPrevInstance as HINSTANCE,_ byval _szCmdLine as string,_ byval _iCmdShow as integer)as integer dim _wMsg as MSG dim _wcls as WNDCLASS dim _hWnd as HWND function=0 with _wcls .style=CS_HREDRAW or CS_VREDRAW .lpfnWndProc=@WndProc .cbClsExtra=0 .cbWndExtra=0 .hInstance=_hInstance .hIcon=LoadIcon(NULL,IDI_APPLICATION) .hCursor=LoadCursor(NULL,IDC_ARROW) .hbrBackground=GetStockObject(WHITE_BRUSH) .lpszMenuName=NULL .lpszClassName=@"HelloWin" end with if(RegisterClass(@_wcls)=FALSE)then MessageBox(null,"Failed to register _wcls","Error",MB_ICONERROR) exit function end if _hWnd = CreateWindowEx(0,_ @"HelloWin",_ "PANORAMIC",_ WS_OVERLAPPEDWINDOW,_ 10,_ 10,_ 200,_ 100,_ NULL,_ NULL,_ _hInstance,_ NULL) _handl=_hWnd UpdateWindow(_hWnd) pc_init(_hWnd) sleep 100 V_A="abcd" V_B=V_A pc_print_string(V_A) pc_print_string(V_B) goto _end _end: while(GetMessage(@_wMsg,NULL,0,0)<>FALSE) TranslateMessage(@_wMsg) DispatchMessage(@_wMsg) wend function=_wMsg.wParam end function
Les variables V_A et V_B sont bien des STRING de FreeBASIC et non des pointeurs ! Donc, l'interpréteur et le compilateur PANORAMIC traitent les chaînes de caractères de manière différente. | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Bug avec a$=b$ Jeu 4 Juin 2015 - 9:49 | |
| Tant mieux, Jean-Debord ! Cela aurait été vraiment inquiétant qu'en version compilée, on rencontre le même problème. Le code que tu as posté: - Code:
-
dim a$, b$
a$ = "abcd" b$ = a$
print a$ print b$
end semble s'exécuter correctement, en version interprétée également. On ne se rend compte du problème que si l'on modifie a$ via une fonction de DLL à laquelle on a passé l'adresse de a$. | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Bug avec a$=b$ Jeu 4 Juin 2015 - 10:38 | |
| Et voici la mise en évidence du bug avec un code en 100 % Panoramic, sans DLL: - Code:
-
dim a$, b$ dim a0%, i%, ax%(3), az%
a$ = "abcd" b$ = a$
a0% = adr(a$) print "adr(a$)="+hex$(a0%)
az% = 0 for i%=0 to 3 ax%(i%) = peek(a0%+i%) next i% for i%=3 to 0 step -1 az% = az%*256 + ax%(i%) next i% print "adresse des données="+hex$(az%) print "premier caractère="+chr$(peek(az%)) print " "
a0% = adr(b$)
print "adr(b$)="+hex$(a0%)
az% = 0 for i%=0 to 3 ax%(i%) = peek(a0%+i%) next i% for i%=3 to 0 step -1 az% = az%*256 + ax%(i%) next i% print "adresse des données="+hex$(az%) print "premier caractère="+chr$(peek(az%))
print print "===> l'adresse des données est la même !"
Voici le résultat: Il faudrait que les données soient réellement copiées et que donc, l'adresse des données soit différente ! | |
| | | jimx78
Nombre de messages : 241 Age : 33 Localisation : Yvelines Date d'inscription : 24/05/2010
| Sujet: Re: Bug avec a$=b$ Jeu 4 Juin 2015 - 10:48 | |
| C'est quoi une adresse de donné ? Cela sert à quoi dans un programme ? Merci d'avance | |
| | | jean_debord
Nombre de messages : 1266 Age : 70 Localisation : Limoges Date d'inscription : 21/09/2008
| Sujet: Re: Bug avec a$=b$ Jeu 4 Juin 2015 - 10:55 | |
| J'ai testé le compilateur avec la DLL suivante (en FreeBASIC) : - Code:
-
extern "Windows-MS"
function StrFunc(byref p as zstring ptr) as integer export dim as string s = *p s = ucase(s) *p = s return 0 end function end extern
Le programme de test : - Code:
-
dim a$, b$, res%
a$ = "abcd" b$ = a$
dll_on "fbdll.dll"
res% = dll_call1("StrFunc", adr(a$))
print a$ print b$
dll_off end
Avec l'interpréteur, j'obtiens 2 fois la chaîne "ABCD" ce qui confirme les observations de Klaus. Avec le compilateur, j'obtiens a$ = "ABCD" et b$ = "abcd" donc seul a$ a été modifié. L'interpréteur et le compilateur ont donc bien des comportements différents ! | |
| | | jean_debord
Nombre de messages : 1266 Age : 70 Localisation : Limoges Date d'inscription : 21/09/2008
| Sujet: Re: Bug avec a$=b$ Jeu 4 Juin 2015 - 10:59 | |
| | |
| | | jimx78
Nombre de messages : 241 Age : 33 Localisation : Yvelines Date d'inscription : 24/05/2010
| Sujet: Re: Bug avec a$=b$ Jeu 4 Juin 2015 - 11:06 | |
| Merci, une autre question, en quel langage de programmation est programmer PANORAMIC ? | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Bug avec a$=b$ Jeu 4 Juin 2015 - 11:06 | |
| Cela sert en lien avec des fonctions d'une DLL.
En Panoramic pur, tu accèdes aux données d'une variable par son nom. Exemple: print a$.
Mais lorsque tu veux accéder à ces données dans une fonction DLL, il faut trouver un moyen de lui passer l'information. Et là, il faut se conformer aux normes de Panoramic que Jack a établies pour interfacer Panoramic et les DLLs. Et en particulier, il y a deux règles très restrictives: 1. tout paramètre passé à une fonction DLL est passé "par valeur", pas "par référence" 2. on ne peut passer que des paramètres de type "integer" Et cela impose une certaine inventivité de la part du programmeur de DLL pour faire ce qu'on a à faire. Le seul moyen de passer une chaîne de caractères (comme un nom de fichier, par exemple) à une fonction DLL, serait de passer la variable de type string contenant cette chaîne. Or, on ne peut passer que des valeurs de type iinteger. Solution: Panoramic met à disposition une fonction intrinsèque adr() qui retourne, sous forme d'une valeur integer, l'adresse de la chaîne de caractères. Cette adresse étant en format integer, on peut la passer à une fonction DLL, et c'est à cette fonction de se débrouiller pour trouver les données en fonction de l'adresse qu'on lui passe.
En réalité, les choses sont un peu plus complexes, car adr(a$) retourne l'adresse d'un pointeur vers les données. C'est pourquoi adr(a$) et adr(b$) dans mon code de démonstration donnent des résultats différents, mais le pointeur vers les données est bien le même.
Un autre aspect de cette notion d'adresse, en lien avec les contraintes d'interface Panoramic/DLL: comme les paramètres sont passés "par valeur", on ne peut en aucun cas modifier un paramètre directement, dans une DLL. Mais si le paramètre est une adresse, alors la fonction dans la DLL peut utiliser cette adresse pour déposer des informations à l'endroit pointé par cette adresse. C'est le moyen que j'utilise pour retourner une chaine de caractères à partir d'une fonction DLL.
Voilà, en gros, quelques éléments de réponse. N'hésite pas à approfondir si le sujet t'intéresse ! | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Bug avec a$=b$ Jeu 4 Juin 2015 - 11:08 | |
| Ah, on s'est croisé. Ce serait plutôt à Jack de te répondre, mais je crois savoir que pour l'essentiel, c'est Delphi. Pour ma part, j'utilise Delphi 6 Personal Edition (version gratuite) pour programmer mes DLLs. | |
| | | jimx78
Nombre de messages : 241 Age : 33 Localisation : Yvelines Date d'inscription : 24/05/2010
| Sujet: Re: Bug avec a$=b$ Jeu 4 Juin 2015 - 11:16 | |
| Exacte^^ Cela ne m'a pas empêcher de lire ton message et de le comprendre ;D C'est intéressant tout ca, en tout cas, bon courage, tu a certainement besoin de jack pour répondre à ton probleme
Autre chose : je dois me mettre à comprendre ta dll KGF.dll je sais pas où me documenter sur les fonctions proposer par celle ci, J'aimerai trouver la fonction qui force la souris à aller a un endroit, et celle pour jouer un son | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Bug avec a$=b$ Jeu 4 Juin 2015 - 11:27 | |
| Regarde la doc dans KGF.chm, ou la doc en ligne accessible via mon site.
Dans la rubrique "Gestion de la souris", tu as les fonctions MousePosition (pour un positionnement relatif dans la fenêtre) et AbsoluteMousePosition (pour un positionnement absolu dans l'écran)
Dans la rubrique "Gestion du Windows Media Player", tu as toutes les fonctions gérant le son et/ou les vidéos. Mais juste pour jouer un son, tu as aussi l'objet Panoramic SOUND et la commande PLAY... | |
| | | Contenu sponsorisé
| Sujet: Re: Bug avec a$=b$ | |
| |
| | | | Bug avec a$=b$ | |
|
Sujets similaires | |
|
| Permission de ce forum: | Vous ne pouvez pas répondre aux sujets dans ce forum
| |
| |
| |