'Memory Access Violation"

Blitz3D Forums/Blitz3D Beginners Area/'Memory Access Violation"

Q(Posted 2005) [#1]
I keep getting this error message when running my compiled code saying "Memory Access Violation". It happens in the first second of the program being run. Why is this happening? Here is my code:

; map editor

Graphics3D 800, 600, 32, 2

SetBuffer BackBuffer()

AppTitle("Map Editor v1.0")

Global t_menu = LoadImage("graphics\t_menu.bmp")
	MaskImage t_menu, 0, 255, 0
Global b_menu = LoadImage("graphics\b_menu2.bmp")
	MaskImage b_menu, 0, 255, 0
Global file = LoadImage("graphics\file.bmp")
	MaskImage file, 255, 255, 0
Global quit = LoadImage("graphics\quit.bmp")
	MaskImage quit, 255, 255, 0
Global n = LoadImage("graphics\n.bmp")
	MaskImage n, 255,255,255
Global p = LoadImage("graphics\p.bmp")
	MaskImage p, 255, 255, 255
Global tiles = LoadAnimImage("\Tiles\Terrains\terrain.bmp",64,64,0,5)
	MaskImage tiles, 255, 255, 255
Global pointer = LoadImage("graphics\mouse.bmp")

Dim map(32, 24)

Global currenttile#=1
Global mapx# = 32
Global mapy# = 24

Global gridon# = 0

Const erase#=0


While Not KeyHit(1)

	; pointer coordinates

	p_x# = MouseX()
	p_y# = MouseY()
	
	Cls
	
	; Button setup
	If ImagesOverlap(pointer, p_x#, p_y#, n, 101, 582) Then buttonon(n)
	If ImagesOverlap(pointer, p_x#, p_y#, n, 101, 582) And MouseHit(1) Then currenttile=currenttile+1
	If currenttile > 4 Then currenttile = 1	
	If Not ImagesOverlap(pointer, p_x#, p_y#, n, 101, 582) Then buttonoff(n)
	
	If ImagesOverlap(pointer, p_x#, p_y#, p, 20, 582) Then button2on(p)
	If ImagesOverlap(pointer, p_x#, p_y#, p, 20, 582) And MouseHit(1) Then currenttile=currenttile-1
	If currenttile < 0 Then currenttile = 4
	If Not ImagesOverlap(pointer, p_x#, p_y#, p, 20, 582) Then button2off(p)
	
	If ImagesOverlap(pointer, p_x#, p_y#, quit, 73, 0) And MouseDown(1) Then End
	
	update()
	controls()

	Text 0,18,"X: "+MouseX()
	Text 0,28,"Y: "+MouseY()
	Text 0,38,"Press the 'G' key to enable the grid."
	
	Flip

Wend
End

; button mouse-over effects

Function buttonon(n)

	FreeImage n
	n = LoadImage("Graphics\n2.bmp")

End Function

Function buttonoff(n)

	FreeImage n
	n = LoadImage("graphics\n.bmp")

End Function

Function button2on(p)

	FreeImage p
	p = LoadImage("graphics\p2.bmp")
	
End Function

Function button2off(p)

	FreeImage p
	p = LoadImage("graphics\p.bmp")

End Function

; update

Function update()

For x#=0 To mapx#
	For y#=0 To mapy#
		DrawImage tiles, x#*64, y#*64,map(x#, y#)
	Next
Next

	DrawImage t_menu, 0, 0
	DrawImage file, 0, 0
	DrawImage quit, 73, 0
	DrawImage b_menu, 0, 540
	DrawImage n, 101, 582 ; next button
	DrawImage p, 20, 582 ; previous button
	DrawImage tiles, 38, 540, currenttile

End Function

Function controls()

	tile_x# = MouseX()/64
	tile_y# = MouseY()/64

	DrawImage pointer, p_x, p_y ; mouse

	If MouseDown(1) And tile_x# < 32 And tile_y# < 24 Then map(tile_x#, tile_y#)=currenttile#
	If MouseDown(2) And tile_x# < 32 And tile_y# < 24 Then map(tile_x#, tile_y#)=0
	
	If KeyHit(34) Then gridon# = +1
	
	grid()
	
	
End Function

Function grid()

If gridon# = 1
If gridon# > 1 Then gridon = 0

For x# = 0 To mapx#
	For y# = 0 To mapy#
		Rect x#*64, y#*64, 64, 64, 0
	Next
Next

EndIf

End Function



Shifty Geezer(Posted 2005) [#2]
Have you got Debug enabled? Otherwise the only errors you ever get are MAVs which don't tell yuo squat!


Q(Posted 2005) [#3]
Yes, I have debug enabled. Hmm.. I don't know what to do. So depressing.

I deleted the grid function and everything involving it. Leaving me with the following code:

; map editor

Graphics3D 800, 600, 32, 2

SetBuffer BackBuffer()

AppTitle("Map Editor v1.0")

Global t_menu = LoadImage("Graphics\t_menu.bmp")
	MaskImage t_menu, 0, 255, 0
Global b_menu = LoadImage("Graphics\b_menu.bmp")
	MaskImage b_menu, 0, 255, 0
Global file = LoadImage("Graphics\file.bmp")
	MaskImage file, 255, 255, 0
Global quit = LoadImage("Graphics\quit.bmp")
	MaskImage quit, 255, 255, 0
Global n = LoadImage("Graphics\n.bmp")
	MaskImage n, 255,255,255
Global p = LoadImage("Graphics\p.bmp")
	MaskImage p, 255, 255, 255
Global tiles = LoadAnimImage("\Tiles\Terrains\terrain.bmp",64,64,0,5)
	MaskImage tiles, 255, 255, 255
Global pointer = LoadImage("graphics\mouse.bmp")

Dim map(32, 24)

Global currenttile#=1
Global mapx# = 32
Global mapy# = 24

Const erase#=0


While Not KeyHit(1)

	; pointer coordinates

	p_x# = MouseX()
	p_y# = MouseY()
	
	Cls
	
	; Button setup
	If ImagesOverlap(pointer, p_x#, p_y#, n, 101, 582) Then buttonon(n)
	If ImagesOverlap(pointer, p_x#, p_y#, n, 101, 582) And MouseHit(1) Then currenttile=currenttile+1
	If currenttile > 4 Then currenttile = 1	
	If Not ImagesOverlap(pointer, p_x#, p_y#, n, 101, 582) Then buttonoff(n)
	
	If ImagesOverlap(pointer, p_x#, p_y#, p, 20, 582) Then button2on(p)
	If ImagesOverlap(pointer, p_x#, p_y#, p, 20, 582) And MouseHit(1) Then currenttile=currenttile-1
	If currenttile < 0 Then currenttile = 4
	If Not ImagesOverlap(pointer, p_x#, p_y#, p, 20, 582) Then button2off(p)
	
	If ImagesOverlap(pointer, p_x#, p_y#, quit, 73, 0) And MouseDown(1) Then End
	
	update()
	controls()

	Text 0,18,"X: "+MouseX()
	Text 0,28,"Y: "+MouseY()
	Text 0,38,"Press the 'G' key to enable the grid."
	
	Flip

Wend
End

; button mouse-over effects

Function buttonon(n)

	FreeImage n
	n = LoadImage("Graphics\n2.bmp")

End Function

Function buttonoff(n)

	FreeImage n
	n = LoadImage("graphics\n.bmp")

End Function

Function button2on(p)

	FreeImage p
	p = LoadImage("graphics\p2.bmp")
	
End Function

Function button2off(p)

	FreeImage p
	p = LoadImage("graphics\p.bmp")

End Function

; update

Function update()

For x#=0 To mapx#
	For y#=0 To mapy#
		DrawImage tiles, x#*64, y#*64,map(x#, y#)
	Next
Next

	DrawImage t_menu, 0, 0
	DrawImage file, 0, 0
	DrawImage quit, 73, 0
	DrawImage b_menu, 0, 540
	DrawImage n, 101, 582 ; next button
	DrawImage p, 20, 582 ; previous button
	DrawImage tiles, 38, 540, currenttile

End Function

Function controls()

	tile_x# = MouseX()/64
	tile_y# = MouseY()/64

	DrawImage pointer, p_x, p_y ; mouse

	If MouseDown(1) And tile_x# < 32 And tile_y# < 24 Then map(tile_x#, tile_y#)=currenttile#
	If MouseDown(2) And tile_x# < 32 And tile_y# < 24 Then map(tile_x#, tile_y#)=0
	
	
	
End Function


Everything works like it should when I test run it, but once compiled into a .exe I am missing a few images, thus causing other parts of the program to not work. The images that are not showing up are n.bmp, n2.bmp, p.bmp, and p2.bmp. This is wierd :S

Also, approximately 26 seconds the program gets the odd 'MAV' error..


WolRon(Posted 2005) [#4]
I would guess it's because you are loading/freeing images on the fly so much like so:
Function button2off(p)

	FreeImage p
	p = LoadImage("graphics\p.bmp")

End Function
I'm sure it would be better to just load all of the images at the beginning of the program and just Do or Don't draw the necessary ones.


big10p(Posted 2005) [#5]
[edit] Arg! Someone beats me to it again. :P

These lines:
If ImagesOverlap(pointer, p_x#, p_y#, n, 101, 582) Then buttonon(n)

If Not ImagesOverlap(pointer, p_x#, p_y#, n, 101, 582) Then buttonoff(n)

cause the button image to be constantly freed and loaded. This is a very bad idea. While not syntactically wrong, it's probably causing chaos because it's being done so frequently.

The best way is to load all your images outside of the main loop and then just display the correct image depending on whether you're pointing on the button, or not.

Also, using global variable names of 'p' and 'n' is not such a good idea. They're not descriptive and simple variable names like this are often used for other things, like For/Next loops.


Sir Gak(Posted 2005) [#6]
Another reason you don't want to load them constantly, is that harddrive access is slower than memory access. Had this been a situation where you were loading from an old fashioned floppy disk, you would screamed at the agonizingly slow disk access.

So I agree with the others: load them once at the beginning of your program, and then just draw them as needed.


Q(Posted 2005) [#7]
Thanks a ton guys! That got rid of the error. I also made the variables more obvious of what they are. I've learned alot here. Just one more problem, for some reason when I click the previous.bmp currenttile should subract 1 but it doesn't. Any clue why it's not?

Again, here's my code:

; map editor

Graphics3D 800, 600, 32, 2

SetBuffer BackBuffer()

AppTitle("Map Editor v1.0")

Global t_menu = LoadImage("Graphics\t_menu.bmp")
	MaskImage t_menu, 0, 255, 0
Global b_menu = LoadImage("graphics\b_menu.bmp")
	MaskImage b_menu, 0, 255, 0
Global file = LoadImage("graphics\file.bmp")
	MaskImage file, 255, 255, 0
Global quit = LoadImage("graphics\quit.bmp")
	MaskImage quit, 255, 255, 0
Global Next1 = LoadImage("graphics\n.bmp")
	MaskImage Next1, 255,255,255
Global next2 = LoadImage("graphics\n2.bmp")
	MaskImage next2, 255,255,255
Global previous = LoadImage("graphics\p.bmp")
	MaskImage previous, 255, 255, 255
Global previous2 = LoadImage("graphics\p2.bmp")
	MaskImage previous2, 255,255,255
Global tiles = LoadAnimImage("Tiles\Terrains\terrain.bmp",64,64,0,5)
	MaskImage tiles, 255, 255, 255
Global pointer = LoadImage("graphics\mouse.bmp")

Dim map(32, 24)

Global currenttile#=1
Global mapx# = 32
Global mapy# = 24

Global gridon# = 0

Const erase#=0


While Not KeyHit(1)

	; pointer coordinates

	pointer_x# = MouseX()
	pointer_y# = MouseY()
	
	Cls
	
	update()
	
	DrawImage t_menu, 0, 0
	DrawImage file, 0, 0
	DrawImage quit, 73, 0
	DrawImage b_menu, 0, 540
	DrawImage tiles, 38, 540, currenttile
	DrawImage pointer, pointer_x, pointer_y
	
	; Button setup
	If ImagesOverlap(pointer, pointer_x, pointer_y, Next1, 102, 582) Then DrawImage next2, 102, 582
	If ImagesOverlap(pointer, pointer_x, pointer_y, Next1, 102, 582) And MouseHit(1) Then currenttile=currenttile+1
	If currenttile > 4 Then currenttile = 0	
	If Not ImagesOverlap(pointer, pointer_x, pointer_y, next1, 102, 582) Then DrawImage Next1, 102, 582
	
	If ImagesOverlap(pointer, pointer_x, pointer_y, previous, 20, 582) Then DrawImage previous2, 20, 582
	If ImagesOverlap(pointer, pointer_x, pointer_y, previous, 20, 582) And MouseHit(1) Then currenttile=currenttile-1
	If currenttile < 0 Then currenttile = 4
	If Not ImagesOverlap(pointer, pointer_x, pointer_y, previous, 20, 582) Then DrawImage previous, 20, 582
	
	If ImagesOverlap(pointer, pointer_x, pointer_y, quit, 73, 0) And MouseDown(1) Then End
	
	controls()

	Text 0,18,"X: "+MouseX()
	Text 0,28,"Y: "+MouseY()
	Text 0,38,"Press the 'G' key to enable the grid."
	
	Flip

Wend
End

; update

Function update()

For x#=0 To mapx#
	For y#=0 To mapy#
		DrawImage tiles, x#*64, y#*64,map(x#, y#)
	Next
Next

End Function

Function controls()

	tile_x# = MouseX()/64
	tile_y# = MouseY()/64

	If MouseDown(1) And tile_x# < 32 And tile_y# < 24 Then map(tile_x#, tile_y#)=currenttile#
	If MouseDown(2) And tile_x# < 32 And tile_y# < 24 Then map(tile_x#, tile_y#)=0
	
	If KeyHit(34) Then gridon# = +1
	
	grid()
	
	
End Function

Function grid()

If gridon# = 1
If gridon# > 1 Then gridon = 0

For x# = 0 To mapx#
	For y# = 0 To mapy#
		Rect x#*64, y#*64, 64, 64, 0
	Next
Next

EndIf

End Function



Yeshu777(Posted 2005) [#8]
You are using both currenttile(int?) & currenttile#(float?)

Not sure if Blitz overlooks this.

Also, as a matter of practive I always tend to use under scores between words (current_tile) - helps when you do stupid things like - currentttile and repeat letters within variable names.

Rgds,


Q(Posted 2005) [#9]
I changed it to a int but I still get the same problem.


WolRon(Posted 2005) [#10]
The problem is your use of the command MouseHit().

Ironically, this is kinda similar to the image loading problem you encountered in the sense that you should only be doing it once per loop.

You see, there is a buffer that holds the number of times that the mouse was hit since the last time you called the MouseHit() command. And every time you check that buffer with the MouseHit() command, the buffer is cleared (zeroed).

In your code you check for a MouseHit() on this line:
If ImagesOverlap(pointer, pointer_x, pointer_y, Next1, 102, 582) And MouseHit(1) Then currenttile=currenttile+1
which is fine BUT then you check for it AGAIN on this line:
If ImagesOverlap(pointer, pointer_x, pointer_y, previous, 20, 582) And MouseHit(1) Then currenttile=currenttile-1
Now, since calling the MouseHit() command the first time cleared the MouseHit buffer, the second call to it will give you an incorrect result of zero hits. Do you understand this?

To avoid this from happening you should only make ONE call to MouseHit() per loop of your game and save that value in a variable. Then you can check the value of that variable as many times as you want in your loop without it 'magically' changing value.

At my Programming Tutorial, I give a few examples of how to do this in my code examples. Take a look. Here is one example:
  wkey = KeyDown(17)				;collect user input
  skey = KeyDown(31)				;It's a good practice to collect these inputs only once
  akey = KeyDown(30)				;per loop.  This will prevent odd behaviors from happening,
  dkey = KeyDown(32)				;for instance if the state of a key changes between multiple
  mouse1 = MouseHit(1)				;checks of that key while still in the same loop.

;...later...
  If mouse1 = True				;check if left mouse button was pressed
    ;blah, blah, blah



Also, just to be helpful, really long lines of code like this:
If ImagesOverlap(pointer, pointer_x, pointer_y, Next1, 102, 582) Then DrawImage next2, 102, 582
If ImagesOverlap(pointer, pointer_x, pointer_y, Next1, 102, 582) And Mouse1 Then currenttile=currenttile+1
If currenttile > 4 Then currenttile = 0	
If Not ImagesOverlap(pointer, pointer_x, pointer_y, next1, 102, 582) Then DrawImage Next1, 102, 582
where you are using redundant If arguments can be reduced to a lot less code. This not only helps make it more readable, but actually makes it faster too since you are only performing the redundant check once.
Try writing it like this (it works exactly the same way):
If ImagesOverlap(pointer, pointer_x, pointer_y, Next1, 102, 582)
	DrawImage next2, 102, 582
	If Mouse1 Then currenttile = currenttile + 1
	If currenttile > 4 Then currenttile = 0	
Else
	DrawImage Next1, 102, 582
EndIf
You see, we reduced the three ImagesOverlap checks to only one check.


Q(Posted 2005) [#11]
Thanks! Where on your website can I find this tutorial, I can't find it?


WolRon(Posted 2005) [#12]
?? The link is in my sig.
BTW, I was editing my reply above some just a few minutes ago, so you might want to reread it, in case you didn't get the updated post.


Q(Posted 2005) [#13]
I'm all about speed, I'll make that syntax a habit. Thanks a ton! =)