Page 1 of 1

[ERROR] Invalid Memory Access ??

Posted: Tue Jun 13, 2006 7:51 pm
by kinjal
Hi,
I have written a program to get 1024 bytes of data from hardware and plot it on screen. The main program continuosuly plots the data on screen while a separate thread is created for capturing the data from hardware. The problem I am facing is that even though memory access locks using Mutex are used, the program crashes with "Invalid Memory Access" error. The "Create Thread Safe Executable" feature of PB is enabled.

Here is my code.

Code: Select all


Global Dim Display_buff.b(1024)

Declare DisplayData()
Declare GetData()

If InitSprite() = 0 ; Try to open DirectX
  MessageRequester("","Problem with DirectX! Cannot continue.",0):End 
EndIf 

hwnd=OpenWindow(1,0,0,520,350,"PLOT",#PB_Window_SystemMenu|#PB_Window_ScreenCentered) 
OpenWindowedScreen(hwnd,4,20,512,300,0,0,0) ; opens a screen on the window

CreateSprite(1,512,200,0) ; creates a temporarily sprite

Mutex = CreateMutex()

CaptureThread = CreateThread(@GetData, #Null)

Repeat
  DisplayData() 
  If WindowEvent() = #PB_Event_CloseWindow
      KillThread(CaptureThread)
      FreeMutex(Mutex)
      End
  EndIf
  Delay(50)
ForEver

;****************************************************************************
; DisplayData
;****************************************************************************
Procedure DisplayData()
  x.w
  old_y1.w: new_y1.w
  old_y2.w: new_y2.w  
  
  StartDrawing(SpriteOutput(1)) 
  Box(0,0,512,200,$000000) 
  
  old_y1 = 0
  old_y2 = 0
  
  LockMutex(Mutex)
  
  For x=0 To 511 
    DrawingMode(1)
    
    new_y1 = Display_buff(x)
    new_y2 = Display_buff(x+512)
    
    LineXY(x-1, old_y1, x, new_y1, RGB(255,0,0))
    LineXY(x-1, old_y2, x, new_y2, RGB(255,0,0))
    
    old_y1 = new_y1
    old_y2 = new_y2
  Next
  
  UnlockMutex(Mutex)
   
  StopDrawing() 
  FlipBuffers() 
  DisplaySprite(1,0,0) 
EndProcedure

;****************************************************************************
; GetData
;****************************************************************************
Procedure GetData()
    Dim Write_buff.b(10)
    Dim Read_buff.b(1024)

    Repeat
      ; These function read data from hardware    
      ;WriteToHW(@Write_buff(0), 3); //Send 3 Bytes to USB Board
      ;bytes_received = ReadFromHW(4, @Read_buff(0), 1024); // Receive 1024 Bytes
      
      If TryLockMutex(Mutex) 
        ;Copy Buffer
        For i=0 To 1023
          Display_buff(i) = Read_buff(i)
        Next i
        UnlockMutex(Mutex) 
      EndIf
            
    ForEver
EndProcedure
Any solutions?

Posted: Tue Jun 13, 2006 8:05 pm
by Trond
Won't help you, but a procedure uses for a thread must absolutely always have EXACTLY four bytes worth of parameters (that could be one long).

Edit: You're getting the address of Data, not Data(). That means, you're getting the address of the variable Data and trying to start a thread at it. You should use @Data().

Posted: Tue Jun 13, 2006 8:08 pm
by netmaestro
Works for me if I change the line:

Code: Select all

CaptureThread = CreateThread(@GetData, #Null) 
to:

Code: Select all

CaptureThread = CreateThread(@GetData(), #Null) 
Pretty common mistake, actually. It's the first thing I look for if someone uses the words "Thread" and "Invalid memory access" in the same sentence.

Posted: Tue Jun 13, 2006 8:10 pm
by kinjal
I dont think that is the reason why it is crashing. I tried using a long parameter just to check but it still crashes.

Posted: Tue Jun 13, 2006 8:15 pm
by kinjal
EVen after putting @GetData() it wasn't working!! showing "Mutex not defined" error. I made this little change i.e declared Mutex as global and is now working! Here is the code if anyone want to refer

Code: Select all

Global Dim Display_buff.b(1024)
Global Mutex.l
 
Declare DisplayData()
Declare GetData()

If InitSprite() = 0 ; Try to open DirectX
  MessageRequester("","Problem with DirectX! Cannot continue.",0):End
EndIf

hwnd=OpenWindow(1,0,0,520,350,"PLOT",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(hwnd,4,20,512,300,0,0,0) ; opens a screen on the window

CreateSprite(1,512,200,0) ; creates a temporarily sprite

Mutex = CreateMutex()

CaptureThread = CreateThread(@GetData(), #Null)

Repeat
  DisplayData()
  If WindowEvent() = #PB_Event_CloseWindow
      KillThread(CaptureThread)
      FreeMutex(Mutex)
      End
  EndIf
  Delay(50)
ForEver

;****************************************************************************
; DisplayData
;****************************************************************************
Procedure DisplayData()
  x.w
  old_y1.w: new_y1.w
  old_y2.w: new_y2.w 
 
  StartDrawing(SpriteOutput(1))
  Box(0,0,512,200,$000000)
 
  old_y1 = 0
  old_y2 = 0
 
  LockMutex(Mutex)
 
  For x=0 To 511
    DrawingMode(1)
   
    new_y1 = Display_buff(x)
    new_y2 = Display_buff(x+512)
   
    LineXY(x-1, old_y1, x, new_y1, RGB(255,0,0))
    LineXY(x-1, old_y2, x, new_y2, RGB(255,0,0))
   
    old_y1 = new_y1
    old_y2 = new_y2
  Next
 
  UnlockMutex(Mutex)
   
  StopDrawing()
  FlipBuffers()
  DisplaySprite(1,0,0)
EndProcedure

;****************************************************************************
; GetData
;****************************************************************************
Procedure GetData()
    Dim Write_buff.b(10)
    Dim Read_buff.b(1024)

    Repeat
      ; These function read data from hardware   
      ;WriteToHW(@Write_buff(0), 3); //Send 3 Bytes to USB Board
      ;bytes_received = ReadFromHW(4, @Read_buff(0), 1024); // Receive 1024 Bytes
     
      If TryLockMutex(Mutex)
        ;Copy Buffer
        For i=0 To 1023
          Display_buff(i) = Read_buff(i)
        Next i
        UnlockMutex(Mutex)
      EndIf
           
    ForEver
EndProcedure 
Thanks guys! PB ROCKS :)

Posted: Tue Jun 13, 2006 8:20 pm
by netmaestro
Yes, I'm sorry I forgot to mention I also fixed:

Code: Select all

Global Mutex = CreateMutex() 

Posted: Tue Jun 13, 2006 8:23 pm
by srod
The 'mutex' variable needs to be global since you use it in the DisplayData() procedure. Alternatively use

Code: Select all

Shared mutex
in the DisplayData() procedure.

Tested and works okay. Just make sure that you're using Trond's and netmaestro's adjustment also.

**EDIT: - too slow! :D

Posted: Tue Jun 13, 2006 8:28 pm
by netmaestro
**EDIT: - too slow!
(coolly blows smoke from pistol barrel and nonchalantly slides sixgun back into holster)
Shucks, Ain't nuthin'.

Posted: Wed Jun 14, 2006 12:54 am
by Rescator
A lot of issues like this can be avoided by using EnableExplicit :)

Posted: Wed Jun 14, 2006 1:08 am
by Dare
Yes, EnableExplict is worth using.

Posted: Wed Jun 14, 2006 7:31 am
by Bonne_den_kule
I use always EnableExplicit

Posted: Wed Jun 14, 2006 7:35 am
by netmaestro
I never do. Another glass of obfuscation, anyone? How about you, traumatic?