Memory Access Violation

Post your coding questions such as 'how to' here.
Post Reply
nacko
Newcomer
Posts: 9
Joined: Thu Aug 21, 2008 8:49 pm
Location: Sweden
Contact:

Memory Access Violation

Post by nacko »

Hi, I'm currently writing a game in CoolBasic, I have stumpled upon an error: Whenever I try to compile my program, it shouts with an error: "Memory Access Violation". But the strange thing is, the error only appear when I try to play an object created within a function. If I place the content inside the function outside of it, it compiles successfully, with no errors whatsoever. I'm confused and the manual is in Finnish so reading through the manual is out of the question.

Here is my code right now, I have seperated them into two sources, the "Main_source" and the "functions" source.

Main_Source:

Code: Select all

'*** Main Source File ***
'*** Includes ***
Include "Functions.CB"

'*** Setup the game
setup_game()
setup_player()


'*** Main Loop ***
Repeat
    PlayObject player_run, 1,8, 0.5

    DrawScreen
Forever 
Functions source:

Code: Select all

'*** Functions ***

'*** Screen Setup function ***
Function setup_game()
    SCREEN 1024, 768, 32
    ShowMouse OFF
    FrameLimit 32
EndFunction 

'*** Player Creation function ***
Function Setup_player()
    player_run = LoadAnimObject("Media\Sprites\Charles_run.png", 100,100, 0,7)
EndFunction 
Now, if I place this line: player_run = LoadAnimObject("Media\Sprites\Charles_run.png", 100,100, 0,7) just before the main LOOP, the program compiles successfully. Cut/Pasting the functions from "functions" source to "Main_Source" has no effect either, the error is still there. Any ideas why this strange behaviour occurs? Please help me out and thanks in advance! :)

Code: Select all

#include "Frank_Sinatra_Rules.h"
mikeful
Moderator
Moderator
Posts: 523
Joined: Mon Aug 27, 2007 8:36 pm
Location: Vaasa, Finalnd
Contact:

Re: Memory Access Violation

Post by mikeful »

"player_run" is local variable to function and game crashes when you try to access non-existing object. Define global variable named "player_run" in function or before you call it.
Pelejä: Pelasta puhe, Grinder
Muuta: Blogi, Twitter
nacko
Newcomer
Posts: 9
Joined: Thu Aug 21, 2008 8:49 pm
Location: Sweden
Contact:

Re: Memory Access Violation

Post by nacko »

Oh, ok. I never knew the Objects where variables. Thanks for the enlightenment! :)

Code: Select all

#include "Frank_Sinatra_Rules.h"
Koodiapina
Forum Veteran
Posts: 2396
Joined: Tue Aug 28, 2007 4:20 pm

Re: Memory Access Violation

Post by Koodiapina »

CoolBasic object is more complex thing than just a variable. Variable has only the address which is needed for commands to access the object in memory.
User avatar
Jare
Devoted Member
Posts: 877
Joined: Mon Aug 27, 2007 10:18 pm
Location: Pori
Contact:

Re: Memory Access Violation

Post by Jare »

Grandi wrote:CoolBasic object is more complex thing than just a variable. Variable has only the address which is needed for commands to access the object in memory.
And this can be easily pointed out:

Code: Select all

my_object = LoadObject("Media/guy.bmp",72)
Text 0,0, my_object
Drawscreen
WaitKey
So this way you can do some debug and check if a variable has an object loaded into it (or image, sound, font, etc). Just print it and if it has some value other than 0, then it contains an object and should work. Just mentioned this for the future if you still run into troubles. ;)
nacko
Newcomer
Posts: 9
Joined: Thu Aug 21, 2008 8:49 pm
Location: Sweden
Contact:

Re: Memory Access Violation

Post by nacko »

Thanks for the share of information, very much appreciated and will come in handy in the future, no doubt. ^^

I was wondering, can you assign object name with a variable?

Like the code below:

Code: Select all

for object_nr = 1 to 10
    object_nr = loadobject("bitmap.bmp")
    positionobject object_nr, rnd(0,100),rnd(0,100)
next object_nr
That would be great for creating lots of objects at once, no? ^^

EDIT: Just tried it, worked perfectly, what a relief! :lol:

Code: Select all

#include "Frank_Sinatra_Rules.h"
User avatar
Jare
Devoted Member
Posts: 877
Joined: Mon Aug 27, 2007 10:18 pm
Location: Pori
Contact:

Re: Memory Access Violation

Post by Jare »

nacko wrote:Thanks for the share of information, very much appreciated and will come in handy in the future, no doubt. ^^

I was wondering, can you assign object name with a variable?

Like the code below:

Code: Select all

for object_nr = 1 to 10
    object_nr = loadobject("bitmap.bmp")
    positionobject object_nr, rnd(0,100),rnd(0,100)
next object_nr
That would be great for creating lots of objects at once, no? ^^

EDIT: Just tried it, worked perfectly, what a relief! :lol:
Yes, you can create multiple objects that way - but after that you can only control one of them (the latest).

An array will become handy in this situation:

Code: Select all

Dim objects(9) 'Make an array for ten objects (0,1,2,3 ... 9)
For i = 0 to 9
    objects(i) = LoadObject("bitmap.bmp")
    PositionObject objects(i), Rnd(0,100),rnd(0,100)
Next i
After that just use another For loop to control each of the objects individually - or put the control commands inside the existing For loop.
nacko
Newcomer
Posts: 9
Joined: Thu Aug 21, 2008 8:49 pm
Location: Sweden
Contact:

Re: Memory Access Violation

Post by nacko »

Yes, you can create multiple objects that way - but after that you can only control one of them (the latest).
which is not entirely true, you can control each object without the suggested array in your post. The objects have been assigned a number (object_nr) which I use to control the objects.

But it is true that using an array is handy in that situationm since they are more flexible than variables.

Code: Select all

#include "Frank_Sinatra_Rules.h"
User avatar
Jonez
Devoted Member
Posts: 575
Joined: Mon Aug 27, 2007 8:37 pm

Re: Memory Access Violation

Post by Jonez »

It seems to be a bug in CB. To my knowledge that shouldn't be possible, so I wouldn't recommend loading objects like that. It seems that if you load an object by using that method, Coolbasic starts from the beginning of the memory. Who knows if it manages to overwrite something valuable.

I'll explain what the next code does if you're paranoid enough not to compile it yourself (it probably doesn't work with your computer anyway):
I load only one object, yet I move two. No MAV. There are two objects moving, one forwards and one backwards. In addition there is still on object in the middle of the screen staying still. Three objects in one load and no MAV. That's definitely not a feature.

Code: Select all

For nbr = 5 To 5
    nbr = LoadObject( "media\guy.bmp" )
Next nbr

Repeat
    MoveObject 1, -1, 0
    MoveObject 5, 1, 0   
    DrawScreen
Forever
It doesn't end here: I managed to mess up the system so badly by testing the code above (nackos one), that whenever I made a For-Next-loop like this: For i = 9 to 10 : Print i : Next i : Waitkey.
It would print out like this: 9 1 2 3 4 5 6 7 8 9 10. Although I can't reproduce that one anymore...

My system now always starts from the beginning of the memory when loading objects. With images it works fine (I've only loaded an object by using that weird method). I even tried to reboot my computer. It solved the For-Next-loop-problem, but not the object-loading one. Does anyone know more about the subject? Am I worrying too much? Or is this all just normal behavior (for a computer, not me)?
-Vuoden 2008 aloittelijan ystävä -palkinnon voittaja-
Image <- protestipelikilpailun voittaja.
Space War
nacko
Newcomer
Posts: 9
Joined: Thu Aug 21, 2008 8:49 pm
Location: Sweden
Contact:

Re: Memory Access Violation

Post by nacko »

Is that method really that much of a problem? The only thing it does is giving the objects one ID-number each. 10 objects, with the IDs of 1,2,3....10. It's the same thing as naming them manually just that it automatically give the objects a name(ID) in a specific order.

Code: Select all

For object_nr = 1 to 2
    object_nr = LoadObject("Media\cow.bmp")
    PositionObject object_nr, Rnd(0,100),rnd(0,100)
Next object_nr

rightflag = 0
leftflag = 0

Repeat
    If RightKey()=1 And rightflag = 0
        rightflag = 1
        PositionObject 1, Rnd(20, 60), Rnd(20, 60)
    ElseIf RightKey()=0 And rightflag = 1
        rightflag = 0
    EndIf
    
    If LeftKey()=1 And leftflag = 0
        leftflag = 1
        PositionObject 2, Rnd(20, 60), Rnd(20, 60)
    ElseIf LeftKey()=0 And leftflag = 1
        leftflag = 0
    EndIf

    DrawScreen
Forever
Here is a code I wrote just now, it works perfectly. I have assigned an ID each for two objects. Object one has the name of 1, and object two have the name of 2. Then, in the main LOOP, I press right-key to randomly place object 1, and the same for object 2, instead that I press the left button. It works perfectly.

One problem though is that if I place the for-next loop inside the Main LOOP, it continually generates objects, even though it past 10.

Code: Select all

#include "Frank_Sinatra_Rules.h"
User avatar
Jare
Devoted Member
Posts: 877
Joined: Mon Aug 27, 2007 10:18 pm
Location: Pori
Contact:

Re: Memory Access Violation

Post by Jare »

nacko wrote:Is that method really that much of a problem? The only thing it does is giving the objects one ID-number each.
Well, I was wrong in my previous post. Of course you can handle the objects like the way you showed. In a very small game I assume it wouldn't be a problem. But only if you don't need to delete the objects. When it comes to the point where you need to delete one object, say object that has ID 5, you end up putting a hole into middle of your object list. And when you go through the list again, there may be no way to indicate if an object has been deleted or not. That's where arrays take place because they give you a possibility to clear reference to a deleted object and make sure you won't try to use them accidentally. Or you can use Types instead of arrays, but that's another (long) story if you are not yet familiar with them.

Though another way to delete objects would be to make them invisible and apply them some value that indicates to the game that no actions should be taken with them anymore. This is not a neat way, but keeps the application from crashing.

I am very interested in learning to manipulate things that CB normally controls through its inbuild commands and functions. This can show us some new ways to get things done. If I go back to on-topic, Memory Access Violation is something that everybody is often running into with CB. That's often because of deleted resources that are tried to be used afterwards. Reading their pointer integers may in some situtations tell whether an resource still exists or not without triggering the application to crash. The pointers can be tried to read with for example PeekInt() and PeekByte() functions, but I'm afraid that does not work for objects, but instead for images, sounds, fonts, type instances and maybe file pointers. It's worth trying.
nacko
Newcomer
Posts: 9
Joined: Thu Aug 21, 2008 8:49 pm
Location: Sweden
Contact:

Re: Memory Access Violation

Post by nacko »

Well, I was wrong in my previous post. Of course you can handle the objects like the way you showed. In a very small game I assume it wouldn't be a problem. But only if you don't need to delete the objects. When it comes to the point where you need to delete one object, say object that has ID 5, you end up putting a hole into middle of your object list. And when you go through the list again, there may be no way to indicate if an object has been deleted or not.
Which is practically the same as an object list of manually entered objects? This is generally just a way to easily and in an efficient matter name identical objects. But I see your point, it's hard to organize lots of objects when they are all named after numbers.
That's where arrays take place because they give you a possibility to clear reference to a deleted object and make sure you won't try to use them accidentally.
Another easy way to prevent the accidental use of deleted object would be some kind of existence check to see if the object currently exist in the program. Like objectexist([object])=0,1 (true, false). If the object does not exist (0) then the desired action on that object will not run. Thus preventing the program from using an non-existing object which would lead to a program crash. Too bad I can't see anything like that in the command reference. It really could've been useful.
If I go back to on-topic, Memory Access Violation is something that everybody is often running into with CB. That's often because of deleted resources that are tried to be used afterwards. Reading their pointer integers may in some situtations tell whether an resource still exists or not without triggering the application to crash. The pointers can be tried to read with for example PeekInt() and PeekByte() functions, but I'm afraid that does not work for objects, but instead for images, sounds, fonts, type instances and maybe file pointers. It's worth trying.
Interesting. Why not have some kind of built in resource checker in the editor (or compiler) which point to errors in the handle of resources in the program? That would be neat. :)

Code: Select all

#include "Frank_Sinatra_Rules.h"
User avatar
Jare
Devoted Member
Posts: 877
Joined: Mon Aug 27, 2007 10:18 pm
Location: Pori
Contact:

Re: Memory Access Violation

Post by Jare »

nacko wrote:
Well, I was wrong in my previous post. Of course you can handle the objects like the way you showed. In a very small game I assume it wouldn't be a problem. But only if you don't need to delete the objects. When it comes to the point where you need to delete one object, say object that has ID 5, you end up putting a hole into middle of your object list. And when you go through the list again, there may be no way to indicate if an object has been deleted or not.
Which is practically the same as an object list of manually entered objects? This is generally just a way to easily and in an efficient matter name identical objects. But I see your point, it's hard to organize lots of objects when they are all named after numbers.
It's hard to organize and I think it's impossible to say if for example integer value 5 has any object enclosed with it.
nacko wrote:
That's where arrays take place because they give you a possibility to clear reference to a deleted object and make sure you won't try to use them accidentally.
Another easy way to prevent the accidental use of deleted object would be some kind of existence check to see if the object currently exist in the program. Like objectexist([object])=0,1 (true, false). If the object does not exist (0) then the desired action on that object will not run. Thus preventing the program from using an non-existing object which would lead to a program crash. Too bad I can't see anything like that in the command reference. It really could've been useful.
Unfortunately that's not the case in CoolBasic. CoolBasic forces commands even if the commands were given objects that do not exist and this causes unhandled error messages. And there is no inbuild ObjectExists() function, as you noticed. I miss it too but I believe that such a function can be made by using functions that were officially meant for reading memory blocks (functions like PeekInt() ).
Why not have some kind of built in resource checker in the editor (or compiler) which point to errors in the handle of resources in the program? That would be neat. :)
CoolBasic just gives us lot of features, but not all the features we would like to have. It's a beta release and very old one. But hopefully we can try to write code that indicates when a resource exists or not. Sometimes it's just hard.

So any new features to the programming language, editor and compiler won't be released for the current version of CoolBasic. All enhancements will be available in CoolBasic V3 that will be published in the future. Though maybe you already are aware of that. :)
nacko
Newcomer
Posts: 9
Joined: Thu Aug 21, 2008 8:49 pm
Location: Sweden
Contact:

Re: Memory Access Violation

Post by nacko »

It's hard to organize and I think it's impossible to say if for example integer value 5 has any object enclosed with it.
I'm not really sure what you mean, can you eloborate a little please? :)

Why would it be impossible to tell if an integer has any enclosed object? Isn't the naming the same as when manually giving the objects the name 1, 2 etc...? the method above should be no different? Or am I totally mistaking this whole naming business? :)

I just tried using this:

Code: Select all

1 = loadobject("Media\korv.bmp")
2 = loadobject("Media\korv.bmp")
which didn't work (got error message: "Can't understand the statement at line 1"), why would the other method be able to name the object numerical then but not this method? I'm confused, both are integers no? :?:

Code: Select all

#include "Frank_Sinatra_Rules.h"
Koodiapina
Forum Veteran
Posts: 2396
Joined: Tue Aug 28, 2007 4:20 pm

Re: Memory Access Violation

Post by Koodiapina »

This is because they are constants.
User avatar
Jare
Devoted Member
Posts: 877
Joined: Mon Aug 27, 2007 10:18 pm
Location: Pori
Contact:

Re: Memory Access Violation

Post by Jare »

nacko wrote:
It's hard to organize and I think it's impossible to say if for example integer value 5 has any object enclosed with it.
I'm not really sure what you mean, can you eloborate a little please? :)

Why would it be impossible to tell if an integer has any enclosed object? Isn't the naming the same as when manually giving the objects the name 1, 2 etc...? the method above should be no different? Or am I totally mistaking this whole naming business? :)
Because there is no ObjectExist() function to do the check. You can have numbers from 1 to 10, but with those numbers you can only make the assumption that the numbers have enclosed objects.

It's almost the same thing when you pick up the result of LoadObject() into a variable. Then you have the pointer (or ID, however you want to call it) stored in the variable. The pointer cannot indicate if the object exists or not - it only leads the CB's build-in commands and functions to the memory location that contains the object if it wasn't deleted. But what you can do with variables is to change the pointer stored in the variable to value 0.

Maybe the following code presents my point more clearly. Run it and press A - the first object will be deleted and the program crashes because it tries to use the deleted object. Run it again and press B - the second object will be deleted and the program keeps running because the second object is handled through a variable that can indicate the object's existence.

Code: Select all

unused_variable = LoadObject("media\guy.bmp") 'This object will be loaded into pointer 1

object = LoadObject("media\guy.bmp") 'This object's pointer will be 2 and the pointer will be stored into a variable
PositionObject object, 0, -30

Repeat
	
	'Move the First object
	MoveObject 1, 1 'With only the number 1, we can't check If the object stille exists so we just assume that it does.
	
	'Move the second object
	If object > 0 Then 'First check If we still have pointer To the object
		MoveObject object, 1
	EndIf
	
	'Delete the First object when pressing A
	If KeyHit(cbKeyA) Then DeleteObject 1
	
	'Delete the second object when pressing B
	If KeyHit(cbKeyB) Then
		DeleteObject object
		object = 0 'Change the pointer so we will notice that the object is deleted
	EndIf
	
	DrawScreen
Forever
nacko wrote: I just tried using this:

Code: Select all

1 = loadobject("Media\korv.bmp")
2 = loadobject("Media\korv.bmp")
which didn't work (got error message: "Can't understand the statement at line 1"), why would the other method be able to name the object numerical then but not this method? I'm confused, both are integers no? :?:
Actually you are now trying to use numbers 1 and 2 as variables, but a variable name needs to begin with an alphabet or _ . The numbers you are now using are actually also the numbers that LoadObject() function calls will return in your program. When you used the For loop to load objects, you didn't actually "load objects into numbers". You just loaded objects and CoolBasic gave them number ids starting from 1. So you cannot assing anything statically into a number.

I'm not sure if I made myself clear. Well.. English is not my mother language. :roll:
User avatar
Jonez
Devoted Member
Posts: 575
Joined: Mon Aug 27, 2007 8:37 pm

Re: Memory Access Violation

Post by Jonez »

When you load an object like this: obj = LoadObject( "media\guy.bmp" ). A specific slot from memory is reserved for the object. The variable "obj" itself points to that memory. That's why you can do this:

Code: Select all

obj = LoadObject( "media\guy.bmp" )
something = obj
MoveObject something, 5
Because "something" and "obj" are basically the same thing. A seemingly random number if you print it out.

Let's say the variable "obj" has a value 1234. This means that you can control this object by using the number, which actually is the objects position in memory. Like this:

Code: Select all

obj = LoadObject( "media\guy.bmp" ) //obj is now 1234.
MoveObject 1234, 5 
This means that when you move an object by using a number, you (accidentally maybe) point to the memory slot the object is in. If you use any other memory slot, it results to MAV.

Maybe all the objects in Coolbasic have always been assigned with a number from the beginning of the memory (e.g. 1, 2), and I just haven't realized it. Nevertheless, if you load an object and then give a command to move an object in memory slot 1, most likely the object you loaded will move. So there actually is no bug, and the loop-failure was because of my own noobness:

Code: Select all

For i = 5 To 6
//first round, i = 5
i = LoadObject( "media\guy.bmp" ) 'reserved to mem slot 1.
//so now i = 1
//next round i is obviously 2 etc...
Next i
So actual numbers (in code) don't have anything to do with variable names OR the place in memory where the object is loaded. It just happens to be 1 with objects and something around 10,6 million with images.

Edit. Although I read what Jare said, I still wrote almost the exact same thing without realizing it. Probably to put things straight with myself or something... :) I blame the language barrier!
-Vuoden 2008 aloittelijan ystävä -palkinnon voittaja-
Image <- protestipelikilpailun voittaja.
Space War
User avatar
Jare
Devoted Member
Posts: 877
Joined: Mon Aug 27, 2007 10:18 pm
Location: Pori
Contact:

Re: Memory Access Violation

Post by Jare »

Jonez wrote: Edit. Although I read what Jare said, I still wrote almost the exact same thing without realizing it. Probably to put things straight with myself or something... :) I blame the language barrier!
Well, I don't blame you. Even if you wrote about the same things, you wrote it differently and that's good. :)

I was in the believe too that objects would have much greater pointer values. But now when they are so small, it gives a nice possibility to opimize memory usage a little bit. Say that you have 250 objects running in your game at the same time (though it's very much) and you keep the pointers in an integer array. Now they are taking 250 * 4 bytes memory which is almost one kilobyte. But you can use byte array instead of integer array and the memory consumption will fall to 250 bytes. It's percentually a big saving even though using one kilobyte would be no disaster.
Post Reply