[ERROR] Invalid Memory Access ??

Just starting out? Need help? Post your questions and find answers here.
kinjal
User
User
Posts: 10
Joined: Thu Apr 06, 2006 8:05 pm

[ERROR] Invalid Memory Access ??

Post 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?
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post 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().
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post 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.
BERESHEIT
kinjal
User
User
Posts: 10
Joined: Thu Apr 06, 2006 8:05 pm

Post 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.
kinjal
User
User
Posts: 10
Joined: Thu Apr 06, 2006 8:05 pm

Post 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 :)
Last edited by kinjal on Tue Jun 13, 2006 8:21 pm, edited 1 time in total.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Yes, I'm sorry I forgot to mention I also fixed:

Code: Select all

Global Mutex = CreateMutex() 
BERESHEIT
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post 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
I may look like a mule, but I'm not a complete ass.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

**EDIT: - too slow!
(coolly blows smoke from pistol barrel and nonchalantly slides sixgun back into holster)
Shucks, Ain't nuthin'.
BERESHEIT
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

A lot of issues like this can be avoided by using EnableExplicit :)
Dare
Addict
Addict
Posts: 1965
Joined: Mon May 29, 2006 1:01 am
Location: Outback

Post by Dare »

Yes, EnableExplict is worth using.
Dare2 cut down to size
Bonne_den_kule
Addict
Addict
Posts: 841
Joined: Mon Jun 07, 2004 7:10 pm

Post by Bonne_den_kule »

I use always EnableExplicit
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

I never do. Another glass of obfuscation, anyone? How about you, traumatic?
BERESHEIT
Post Reply