Page 1 sur 1

Invalid acces memory étrange[résolu]

Publié : mer. 14/janv./2009 21:23
par Anonyme
Voila , j'appelle une fonction qui me créer un engrenage
cette fonction me retourne un pointeur , je l'utilise pour identifier l'engrenage.
mais lorsque je veut créer un deuxième engrenage , j'ai un "invalid memory" qui apparait sur un allocatememory()...

Voila le code :

Code : Tout sélectionner

InitSprite() : InitKeyboard() : InitMouse() : InitSprite3D()
  OpenScreen(800,600,32,"") : UsePNGImageDecoder()
  
  Structure Vertex
    x.f
    y.f
  EndStructure
  
  Structure Engrenage
   *Vertices.i
   NbVertices.i
   x.f
   y.f
   Angle.f
   Radius.l
  EndStructure
  
  Procedure.i MakeEngrenage(X,Y,Radius,NbTheet,TheetHeight)
  
  Protected Sub = 5
  Protected AngleStep = 360 / ((NbTheet*2)*Sub)

  *E.Engrenage  = AllocateMemory(  SizeOf(Engrenage) )
  *E\Vertices       = AllocateMemory(  SizeOf(Vertex) * AngleStep  )
  *E\NbVertices = 360 / AngleStep
  *E\Radius =Radius
   *E\x = X
   *E\y = Y
   Radius_ = Radius
   
  For i = 0 To 360  / AngleStep
 
    C+1
    C%Sub

    
    If C=Sub-1
    D+1
    D%2      
    
      If D=1
        Radius_ = Radius +TheetHeight
      EndIf
      
       If D=0
        Radius_ = Radius 
      EndIf
       
    EndIf 
 
  X_.f = X + Radius_ * Cos( ( i * AngleStep) * #PI / 180 )
  Y_.f = Y + Radius_ * Sin ( ( i * AngleStep) * #PI / 180 )
 
 PokeF(*E\Vertices+ ( i * SizeOf(Vertex) + OffsetOf(Vertex\x)) ,X_ )
 PokeF(*E\Vertices+ ( i * SizeOf(Vertex) + OffsetOf(Vertex\y)) ,Y_ )
    
  Next 
  
  ProcedureReturn *E  
  EndProcedure
  
  Procedure DrawEngrenage(*Engrenage.Engrenage)
  StartDrawing(ScreenOutput())
  With  *Engrenage
       For i = 0 To \NbVertices-1
          x1.f = PeekF(\Vertices + ( i *SizeOf(Vertex) + OffsetOf(Vertex\x))) 
          y1.f = PeekF(\Vertices + ( i *SizeOf(Vertex) + OffsetOf(Vertex\y)))
          
          x2.f = PeekF(\Vertices + ( (i+1) *SizeOf(Vertex) + OffsetOf(Vertex\x))) 
          y2.f = PeekF(\Vertices + ( (i+1) *SizeOf(Vertex) + OffsetOf(Vertex\y)))
          
          LineXY(x1,y1,x2,y2,$000000)
                                
      Next 
      
      ; On ferme
      
          x1 = PeekF(\Vertices + ( 1*SizeOf(Vertex) + OffsetOf(Vertex\x))) 
          y1 = PeekF(\Vertices + ( 1*SizeOf(Vertex) + OffsetOf(Vertex\y)))
          
          x2 = PeekF(\Vertices + ( \NbVertices *SizeOf(Vertex) + OffsetOf(Vertex\x))) 
          y2 = PeekF(\Vertices + ( \NbVertices *SizeOf(Vertex) + OffsetOf(Vertex\y)))
          
          LineXY(x1,y1,x2,y2,$000000)
      
      DrawingMode(#PB_2DDrawing_Outlined)
          Circle(\X,\Y,\Radius/1.5,$000000)
      
      
      
  EndWith
  StopDrawing()
  EndProcedure
  
  

  
  

  A= MakeEngrenage(400,300,150,10,20)
  Debug "A ok"
  B =  MakeEngrenage(400,300,150,10,20)
  Debug "B ok"
  
  Repeat
    ExamineKeyboard()
      ClearScreen($FFFFFF)
      
      
      
            DrawEngrenage(A)
            DrawEngrenage(B) 
            
    FlipBuffers(0)
  Until KeyboardPushed(#PB_Key_Escape)

Publié : mer. 14/janv./2009 21:46
par tmyke
En regardant vite fait, ligne 32, ta boucle

Code : Tout sélectionner

For i = 0 To 360  / AngleStep
donne forcement plus d'itération que de AllocateMemory( SizeOf(Vertex) * AngleStep ) aloué,
vue que 360/AngleStep est > à AngleStep
donc violation mémoire dans cette boucle quand tu fait tes

Code : Tout sélectionner

 PokeF(*E\Vertices+ ( i * SizeOf(Vertex) + OffsetOf(Vertex\x)) ,X_ )
 PokeF(*E\Vertices+ ( i * SizeOf(Vertex) + OffsetOf(Vertex\y)) ,Y_ )
Le fait que cela plante lors d'une tentative de seconde allocation d'un Engrenage est trompeur,
car l'erreur se produit en fait lors des opérations sur le premier.

Publié : mer. 14/janv./2009 22:04
par Anonyme
Merci , mais le problème persite , j'ai corrigé une partie de mon erreur :
Protected Sub = 5
Protected AngleStep = 360 / ((NbTheet*2)*Sub)

*E.Engrenage = AllocateMemory( SizeOf(Engrenage) )
*E\Vertices = AllocateMemory( SizeOf(Vertex) * (360 / AngleStep) )

Qui pour 100 vertices alloue bien 800 bytes de mémoire.
L'allocation plante là on c'est en gras. lors du second appel , j'ai beau agrandir artificiellement la taille de mémoire , ca ne change rien.

Publié : mer. 14/janv./2009 22:42
par tmyke
En effet cela plante toujours.

En fait il semble que l'allocation soit enore trop 'courte' et d'ailleurs en commentant les Poke, cela
ne plante plus. C'est bien que c'est ligne vont écrire ou il ne faut pas.

Je viens de voir la ligne

Code : Tout sélectionner

  For i = 0 To 360  / AngleStep
en la remplaçant par

Code : Tout sélectionner

  For i = 0 To (360  / AngleStep)-1

cela parait plus logique, et de plus le code ne plante plus et j'ai une belle roue denté à l'ecran.

Publié : mer. 14/janv./2009 22:46
par lionel_om
J'ai déjà eu des pb de ce genre.
Pour débugger on peut utiliser ça (code eu sur le forum anglais) :

Code : Tout sélectionner

Procedure ValidatePBHeap(LineNumber)
  Protected Heap
  !mov eax, dword [_PB_MemoryBase]
  !mov [p.v_Heap], eax
  If HeapValidate_(Heap, 0, 0) = 0
    MessageRequester("Error", "PB Memory Heap invalid at Line:  " +Str(LineNumber))
  EndIf 
EndProcedure 

Macro _validate
  ValidatePBHeap(#PB_Compiler_Line)
EndMacro
Il n'y a plus qu'à utiliser '_validate' à plusieurs endroit pour voir où ca plante...

/Lio

Publié : mer. 14/janv./2009 23:05
par lionel_om
C'est tes PokeF() qui sont en cause (dans MakeEngrenage() ).
Dans ton exemple, tu réserves 24 octets pour *E\Vertices, or dans ta boucle For/Next, tu vas bien plus loin que ces 24...jusqu'à 964.

Regarde de ce coté...

J'ai mis la taille à 2000 et ca marche...

/Lio

Publié : mer. 14/janv./2009 23:13
par Anonyme
Oui , j'ai déjà corrigé le problème.
le problème venais de là et de la boucle for - next
merci les gens , on en apprend tout les jours. :D