Page 1 sur 1

Procedure et allocatememory

Publié : jeu. 27/août/2009 8:42
par Le psychopathe

Code : Tout sélectionner

Procedure SendMessage(ClientID,type, Message$)
  *buffer2 = AllocateMemory(4+Len(Message$))
  PrintN("Message serveur : " + Message$ + " pour " + Str(ClientID))
   PokeL(*Buffer2,type)
   PokeS(*Buffer2+4,Message$)
  SendNetworkData(ClientID,*Buffer2,MemorySize(*Buffer2))
EndProcedure

Cette procédure plante régulièrement : error read memory
Elle plante moins avec le freememory supprimé à la fin de celle-ci mais cela plante encore.

Je pense que la procédure va plus vite que la mémoire. Je m'explique :
J'envoie des message en rafale, donc la procédure est appelée à un rythme soutenue. Serait- il possible que cela plante car la mémoire n sait pas vider assez vite.

Je commence à péter un câble xD

Donc dans ce cas serrait-il plus judicieux de faire un global *Buffer alloué une seule fois au début du programme. et de le remplir d'un caractère quelconque. Le seul soucis c'est que cela me contraint à envoyer des gros *buffer même pour un message de deux lettres xD

Un petit log sur les erreurs clients avec allocate comme pour le serveur xD

Code : Tout sélectionner

[11:23:58] Waiting for executable to start...
[11:23:58] Executable type: Windows - x86  (32bit)
[11:23:58] Executable started.
[11:24:35] [ERROR] Line: 411
[11:24:35] [ERROR] Can't allocate a memory block of size 0.
[11:24:45] The Program was killed.
[11:24:46] Waiting for executable to start...
[11:24:46] Executable type: Windows - x86  (32bit)
[11:24:46] Executable started.
[11:26:08] [ERROR] Line: 222
[11:26:08] [ERROR] Invalid memory access. (read error at address 0)

Publié : jeu. 27/août/2009 10:35
par Atomo
Tu utilises des threads dans ton programme ?
Si c'est le cas, actives le mode threadsafe dans les options du compilateur pour voir.

Publié : jeu. 27/août/2009 10:37
par gnozal
Il y a une erreur ici :

Code : Tout sélectionner

*buffer2 = AllocateMemory(4+Len(Message$))
Ne jamais oublier qu'une chaîne est terminée par un zéro, donc ajouter 1 à la taille allouée (en mode ANSI).

Taille =
4 -> entier long
+ Len(Message$) -> chaîne
+ 1 -> zéro terminal (ne pas oublier)

Et ne pas oublier de libérer la mémoire allouée lorsqu'elle ne sert plus.

Enfin, pour plus de compatibilité avec les modes UNICODE ou le x64, on peut utiliser SizeOf(LONG) ou SizeOf(INTEGER) au lieu de 4, SizeOf(CHARACTER) au lieu de 1 (zéro terminal), MemoryStringLen() au lieu de Len().

Publié : jeu. 27/août/2009 12:50
par Le psychopathe
gnozal a écrit :Il y a une erreur ici :

Code : Tout sélectionner

*buffer2 = AllocateMemory(4+Len(Message$))
Ne jamais oublier qu'une chaîne est terminée par un zéro, donc ajouter 1 à la taille allouée (en mode ANSI).

Taille =
4 -> entier long
+ Len(Message$) -> chaîne
+ 1 -> zéro terminal (ne pas oublier)

Et ne pas oublier de libérer la mémoire allouée lorsqu'elle ne sert plus.

Enfin, pour plus de compatibilité avec les modes UNICODE ou le x64, on peut utiliser SizeOf(LONG) ou SizeOf(INTEGER) au lieu de 4, SizeOf(CHARACTER) au lieu de 1 (zéro terminal), MemoryStringLen() au lieu de Len().
Merci je vais faire les modifications. Juste une petite chose :
En ajoutant Protected je n'ai pas eu de plantage.

Code : Tout sélectionner

Procedure SendMessage(ClientID,type, Message$)
  Protected *buffer2 = AllocateMemory(4+Len(Message$))
  PrintN("Message serveur : " + Message$ + " pour " + Str(ClientID))
   PokeL(*Buffer2,type)
   PokeS(*Buffer2+4,Message$)
  SendNetworkData(ClientID,*Buffer2,MemorySize(*Buffer2))
  
EndProcedure
Et non je n'utilise pas de thread pour le moment ;)
C'est juste un chat, qui va se terminer en mini réseau privé peer to peer d'ici peu. On va dire que je teste déjà avec des chaînes avant d'envoyer des fichiers.

Publié : jeu. 27/août/2009 18:55
par Anonyme2
Je te renvoie à l'article du blog PB ici (en anglais ...) sur la corruption mémoire, excellent article avec une procédure permettant de trouver ses erreurs lorsque l'entête mémoire système a été écrasée par les données écrites (surtout dans des programmes longs)

http://www.purebasic.fr/blog/?m=200810

Pour l'avoir utilisée, elle fonctionne parfaitement et m'a permis de trouver mes erreurs sur la mémoire à plusieurs reprises.

Il faut également à chaque allocation de mémoire, tester si celle-ci est bien allouée car il arrive que ça échoue et si on utilise ou supprime la mémoire qui n'existe pas, ça plante.

Tu devrais suivre les bons conseils de gnozal car si la taille allouée ne correspond pas à celle utilisée, on a des erreurs difficiles à trouver (lorsque l'on écrit plus de caractères que la taille mémoire allouée), mais avec la procédure du blog, on arrive à débugger.