Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Unhandled Exception etc...: Access Violation Reading Location 0x00000000

Credits go to Indeterminatus, Tobias Dammers, and Zaphos for helping out!
This thread is locked; no one can reply to it. rss feed Print
Unhandled Exception etc...: Access Violation Reading Location 0x00000000
bamccaig
Member #7,536
July 2006
avatar

hey guys! I've been trying to learn Allegro and finally found a tutorial so I started doing it. It is a LoomSoft's tutorials for "Newbies". So far it's going great. It's got me really excited about Allegro!

Anyway, while doing the 8th lesson in the series <http://www.loomsoft.net/resources/alltut/alltut_index.htm> I have come across a little snag. My problem is not related to the code in the tutorial. The tutorial is going fine. The problem appears to be with my OO approach to the tutorial. In other words, I've been trying to encapsulate the functionality in classes to simplify the code and clean it up a little.

I've attached a copy of the 'project' code so you can compile it yourself and see what's happening <*EDIT* Added link to attachment for convenience: http://www.allegro.cc/files/attachment/591278>. I would give you more for output, but I can't figure out how to get a call stack at the moment and I gotta leave for work in a minute (to work on JavaScript :'().

Sorry there is no makefile, etc., but I haven't yet learned to write a makefile and I was doing lessons 7 and 8 in Windows with VS .NET 2003 anyway (I did the first 6 in Linux and wanted to see if I could get them working in Windows too). I was going to leave the project files in the loomsoft-tutorial/src/win/ directory, but I wasn't sure if it was legal to distribute them from an educational version of the IDE, etc. ::)

Anyway, the project compiles okay, I think, but when I execute the resulting program I get the following:

Unhandled exception at 0x004013c0 in lesson8.exe: 0xC0000005: Access violation reading location 0x00000000.

I haven't had much time to look into the cause of the problem, but my Google searches didn't return anything related. (The few forums that looked to have the same problem were guided in a different direction and never concluded the exception).

I would throw in exception handling to prevent a fatal crash, but the code VS .NET 2003 is pointing to as the cause is not doing anything but setting a member in an accessor method. Granted, the member is also an object, but I thought it was still straight-forward... I honestly haven't had a chance to use C/C++ before now in months.

Anyway, I found that my Debug and Release projects appear to throw the same type of exceptions at different points in the code too. Hmmm.

If you have a chance please look at, compile, and execute the project and tell me what's wrong; or just tell me what could cause an "access violations" exception. I thought maybe it was related to the public, private, and protected keywords so to rule that out I put everything public temporarily... So don't worry about that, the members were all private/protected. But it's still throwing the same exception. ???

I'd also like feedback on the directory structure of my project since I'm trying to do it the right way. I really prefer the *nix directory structure to Windows'.

/ - This is the project root, for example, loomsoft-tutorial.
bin - Was going to put executables or dlls here for distribution.
data - I couldn't find the "right" directory to put data such as images in so I just created a data directory. What do you guys do?
include - The main header files are here.
lib - Was going to put any static libraries here.
src - As you can see, the main source code files are here.
src/win - Was putting my VS .NET 2003 project files here.
src/linux - Was planning to put Linux specific files here, if any.

Please note the duplicate data directory (/src/data/) is only there so I could get VS .NET 2003 to see them for debugging... I'm not sure of the right way to do it, nor the right place to have the project files vs. the data files. I'd like feedback.

Thanks a lot! 8-)

Tobias Dammers
Member #2,604
August 2002
avatar

Without looking at your project, I'd say you're dereferencing NULL.
In other words, either you do something like this directly:

int* someptr = 0;
*someptr = something; // this crashes

...or, more likely, you call a member function of a NULL object. Technically, that in itself isn't a problem (unless the function is virtual), but a member function will typically access member variables, and if you call a member function on a NULL object, this means dereferencing NULL. Example:

class foo {
  protected:
    int bar;
  public:
    void set_bar(int newbar) { bar = newbar; }
};

int main() {
  foo* my_foo = 0;
  my_foo->set_bar(23); // this will crash
  return 0;
}

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

bamccaig
Member #7,536
July 2006
avatar

Yeah, that sounds like it could be related... I think the objects themselves are instanciated, however, there might be references to members that are null (including objects as members)... If a member is NULL can you not return it?

int get_bar(void)
{
   return bar;         // Would this crash if bar is NULL?
}

// Should I be doing this instead:

int get_bar(void)
{
    if(bar != NULL)
        return bar;
    else
        return NULL;
}

I just glanced at your post though so I'm not sure I fully grasped it. I'm thinking maybe it is possible for that to work with primitive types. If so what if you tried to return a NULL object?

myOBJECT *get_object(void)
{
    return object;    // Will this crash when object is NULL?
}

// Should I do this:

myOBJECT *get_object(void)
{
    if(object != NULL)
        return object;
    else
        return NULL;
}

Zaphos
Member #1,468
August 2001

Quote:

or just tell me what could cause an "access violations" exception. I thought maybe it was related to the public, private, and protected keywords so to rule that out I put everything public temporarily...

The public, private and protected keywords are enforced at compile time, not at run time: they may cause your program to fail to compile, but they should not cause it to crash.
An "access violation" means your code was trying to access memory that your program does not 'own' at all; in this case, location 0x0, or NULL. Note that it is fine to return NULL; the problem is when you try to access the memory at location NULL. So "return NULL" is fine, and if object == NULL, "return object" is fine, but "return *object" and "return object->fieldName" will both cause your program to crash, because they're trying to look inside the "object" pointer to see the memory it's pointing to.

MSVC should have a debugger built in -- try running the program with the debugger. Then it should halt execution on the error and tell you where in the code it's happening.

Indeterminatus
Member #737
November 2000
avatar

Quote:

int get_bar(void)
{
   return bar;         // Would this crash if bar is NULL?
}

Hm, judging by your post, bar is not a pointer (but an int). If it is in fact a int*, it would have to be:

int get_bar(void)
{
  return *bar;  // Argh! Dereferencing null pointer! Bad!
}

int* get_bar(void)
{
  return bar;   // Safe in any case, as there's no dereferenciation.
}
// However, get_bar() might be NULL, so be careful with its return value.

Quote:

int get_bar(void)
{
    if(bar != NULL)
        return bar;
    else
        return NULL;
}

This is not different to just return bar;. With return *bar;, however, it's a completely different story.

Same thing applies to non-primitive data types.

_______________________________
Indeterminatus. [Atomic Butcher]
si tacuisses, philosophus mansisses

Tobias Dammers
Member #2,604
August 2002
avatar

Your comments, plus my comments.

1int get_bar(void)
2{
3 return bar; // You: Would this crash if bar is NULL?
4 // Me: No. It would crash if this (the "this" pointer) is NULL.
5}
6 
7// You: Should I be doing this instead:
8// Me: No.
9 
10int get_bar(void)
11{
12 if(bar != NULL)
13 return bar;
14 else
15 return NULL;
16}

Let's review the concept of a pointer.
A pointer is a variable with a value. But unlike "normal" variables, the value a pointer holds is not a number, a character, or an object, but rather a memory address. Just like real-life addresses, this address tells you where something is. So if you declare these two variables:

int a = 25;
int* b = &a; // initialize b to point to a

b tells you where to find a. Of course this example is trivial, but that's not the point here.
The problem is that in order to use a chunk of memory, you need to first allocate it properly; that is, you need to ask the OS for some memory. (You don't need to worry about this for normal (non-pointer) variables, since C does all the dirty work for you with these.)
Now if a pointer points somewhere un-allocated (not just NULL, but any memroy address that doesn't "belong" to you), you may be "lucky", and be granted access to this non-allocated memory (this is not a good thing though: at any given time, any other process in the system may rightfully claim "your" memory, and you and the other process will be overwriting each other's memory). Usually though, the OS will prevent you from doing this, and throw a runtime exception at you.
As long as you don't access the memory though, all the pointer does is point to it.

So how do situations like the above arise? There are a number of common causes for these so-called "stray pointers".
1) Uninitialized pointers. Example:

int* a;
*a = 27; // a may point to anything, but not to anything valid

2) Returning pointers to local variables. Example:

int* foo() {
  int bar;
  return &bar; // bar loses focus right after returning, so the pointer is invalid
}

3) Not checking against NULL where this would be appropriate. (It is common practice for functions to return NULL on failure; if a function is documented to do so, please check). Example:

BITMAP* bmp = load_bitmap("my_image.bmp", NULL);
draw_sprite(screen, bmp, 20, 20); // if bmp is NULL, this can crash!

4) Calling class methods on NULL pointers. Example:

class foo {
  protected:
    int bar;
  public:
    int get_bar() { return bar; }
};

int main() {
  foo myfoo = NULL;
  cout << myfoo->get_bar(); // myfoo is NULL, so this will crash.
}

5) Not setting pointers to NULL after freeing their memory. Example:

int* a = malloc(sizeof(int) * 15);
int i;
for (i = 0; i < 15; ++i)
  a<i> = i*i;
free(a);
printf("%i", a[7]);

6) Overflowing buffers. (Not really a stray pointer example, but still a common cause for an access violation.) Example:

int* a = malloc(sizeof(int) * 15);
int i;
for (i = 0; i < 15; ++i)
  a<i> = i*i;
printf("%i", a[32]);

7) Passing NULL to a function that doesn't expect it. Early versions of allegro's destroy_bitmap() had this problem IIRC.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

bamccaig
Member #7,536
July 2006
avatar

1 
2// I guess I will run through the basics to make sure I remember.
3int x=5;
4int* y;
5int* z;
6int** cRaZy;
7int*** YzArC;
8myOBJECT* ptr_objObject = NULL;
9myOBJECT objObject = NULL;
10 
11// I wonder if it would also work to just define them on one line as...
12int* a, b; // Would b also be a pointer or just a?
13 
14/*
15 * I don't actually know how to release the memory of a pointer so I will
16 * only guess. Please tell me how to do it correctly. Since I never set
17 * a or b to an address do I need to call free()? What does free() do?
18 */
19a=NULL;
20b=NULL;
21 
22/*
23 * Can I set the value of y without it having an address set? I'm not very
24 * familiar with malloc() (I think I've used it, likely in OpenGL tutorials),
25 * but it seems like that would be what that is for - meaning this will not work
26 * and could (likely will) crash.
27 */
28*y = 3; // Crash!! ???
29 
30// In order to point y to the value of x I would do this?
31y = &x; // Point to the value of x (5).
32 
33// In order to access the value of x I could now do either of these?
34printf("x=%d and *y=%d\n", x, *y);
35 
36// In order to modify the value of x I could now do either of these?
37x = 6;
38printf("x=%d and *y=%d\n", x, *y);
39 
40*y++;
41printf("x=%d and *y=%d\n", x, *y);
42 
43// In order to set z to x I could now do either of these?
44z = &x;
45printf("x=%d and *y=%d and *z=%d\n", x, *y, *z);
46 
47z = y;
48printf("x=%d and *y=%d and *z=%d\n", x, *y, *z);
49 
50/*
51 * I'm guessing free() releases the memory pointed to by a pointer, but since z is
52 * pointing to memory still in use by x and y I shouldn't free it, right?
53 */
54z=NULL;
55 
56// Set cRaZy to the address of pointer y. (I'm just trying to grasp it fully)
57cRaZy = &y;
58 
59// Set y to NULL - we don't need it anymore.
60y=NULL;
61 
62// So to get the value of x from cRaZy I would do what?
63printf("**cRaZy=%d\n", **cRaZy);
64 
65// Set YzArC to the address of pointer cRaZy.
66YzArC = &cRaZy;
67 
68// Set cRaZy to NULL because I'm done with it.
69cRaZy = NULL;
70 
71// So to get the value of x from YzArC I would do this?
72printf("***YzArC=%d\n", ***YzArC);
73 
74free(YzArC);
75YzArC=NULL;
76 
77// At this point could a reference to x cause a crash/exception?
78 
79// So does the new operator create the object and return the address? For example:
80ptr_objObject = new myOBJECT();
81 
82/*
83 * ptr_objObject is now equal to the address where the instance of myOBJECT
84 * was created?
85 */
86 
87// Call a method from object pointed to be ptr_objObject.
88ptr_objObject->method1();
89 
90// Set objObject equal to the object pointed to by ptr_objObject.
91objObject = *ptr_objObject;
92 
93/*
94 * Release objObject resources because I have a copy in objObject? I'm kinda
95 * guessing...
96 */
97free(ptr_objObject);
98ptr_objObject = NULL;
99 
100// Call a method from objObject.
101objObject.method1();
102 
103// Clean up objObject - Release resources.
104free(objObject);
105objObject = NULL;
106 
107// Hurray! We'll never see this, will we? ;)
108exit(0);

Intended Output:

x=5 and *y=5
x=6 and *y=6
x=7 and *y=7
x=7 and *y=7 and *z=7
x=7 and *y=7 and *z=7
**cRaZy=7
***YzArC=7
method1() writes... Called!
method1() writes... Called!

EDIT

(Keep in mind I'm not very experienced at this so the above code likely doesn't work at all. Some of it is right, but some parts are not.)

Thanks, guys. I couldn't remember the details of pointers and objects in C++, but this thread refreshed it a bit.

EDIT

And I just stumbed on my problem. I wrote this code late with work in the morning weighing on my shoulders. I was enjoying the coding and didn't want to have to stop. I wanted to get as much done as possible so I was rushing. :-[

The tutorial creates a "bounding box" for collision detection using the top left corner position of the bitmap for the top and left edge of the bounding box. It also uses the width and height of the bitmap to get the right and bottom edge of the bounding box. It was on my mind to make sure all of these values were set before I called update_boundingbox() which sets them, but in my rush I neglected the bitmap :(. The problem was as follows:

1 
2void Object::update_boundingbox(void)
3{
4 mobjBoundingBox->TopLeft->x(x());
5 mobjBoundingBox->TopLeft->y(y());
6 
7 /*
8 * It was possible to get here before the bitmap was set, which was exactly
9 * what was happening. As a result, the bitmap was referencing inaccessible
10 * memory.
11 */
12 
13 mobjBoundingBox->BottomRight->x(x()+mobjBitmap->w()); // Oh noes!
14 mobjBoundingBox->BottomRight->y(y()+mobjBitmap->h()); // Oh noes!
15}

The code has now been changed to this:

1 
2void Object::update_boundingbox(void)
3{
4 if(mobjBitmap != NULL && x() != NULL && y() != NULL)
5 {
6 mobjBoundingBox->TopLeft->x(x());
7 mobjBoundingBox->TopLeft->y(y());
8 mobjBoundingBox->BottomRight->x(x()+mobjBitmap->w());
9 mobjBoundingBox->BottomRight->y(y()+mobjBitmap->h());
10 }
11 else
12 {
13 mobjBoundingBox->TopLeft->x(NULL);
14 mobjBoundingBox->TopLeft->y(NULL);
15 mobjBoundingBox->BottomRight->x(NULL);
16 mobjBoundingBox->BottomRight->y(NULL);
17 }
18}

I can't guarantee it's the best way (in fact I see improvements to be made already), but it's mostly a place to start to get back into it... The program is currently running 'til close. ;D

Tobias Dammers
Member #2,604
August 2002
avatar

Let me see.
OK, you have to separate 2 concepts in your head: Memory allocation and pointers.
Memory allocation is handled by malloc() and free(). Memory allocation means that the OS reserves a chunk of memory for you; after you have allocated some memory, it is "yours", and you can write to it and read from it.

You can compare pointers to phone numbers:
the pointer itself - a rolodex card with a phone number
the pointer's value - a phone number
the memory pointed to - the phone connected to the number

Now, storing a value (any value) in a pointer is the same as writing down a phone number on a rolodex. Nothing bad happens when you write down a phone number that doesn't exist. But if you try to call it, you will get an error message (segfault). The problem is that you cannot see from the phone number alone whether it's valid or not. On a rolodex card, you might use a '?', or a blank sheet - with pointers, we use the value NULL.
Now for the allocation. Allocating means telling the telephone company that you want to connect a new telephone (malloc()); the phone company will look for a free number, connect the phone for you and tell you the number (the return value of malloc()). When you don't need it anymore, you ask the company to disconnect the phone (you call free()); you need to give them the number for that (you pass the pointer as an argument to free()). Once the phone has been disconnected, you cannot call that number anymore; the phone company can now give the number to someone else.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

bamccaig
Member #7,536
July 2006
avatar

Thanks again, Tobias. I think I understand malloc()/free() now.

My next question is about new/delete. In my program, I'm instanciating classes with the new operator:



PLAYER *objPlayer = new PLAYER(0, 0);
SHIP *objShip = new SHIP(0, 0);

I'm not sure the right way to clean up the memory so I wanted to check with you. I'm not using malloc() to allocate their memory (at least not directly???), so will free() work to deallocate/release the memory?

Also the PLAYER and SHIP classes have pointers as members so I assumed I had to write a destructor to free that memory. Those members are also instanciated using the new operator. What I currently am doing (and not sure if it's actually cleanup up right) is:

void OBJECT::~OBJECT()   // PLAYER and SHIP inherit from OBJECT.
{
    /*
     * There is an allegro BITMAP in my class so I deallocate it the
     * normal way:
     */
    destroy_bitmap(mobjBitmap);

    // Destroy pointers...
    delete mobjBoundingBox;
    delete mobjPosition;
}

Then at the end of main I do this:

    // Cleanup pointers.
    destroy_bitmap(objBuffer);
    delete objPlayer;
    delete objShip;

???

Zaphos
Member #1,468
August 2001

Quote:

I'm not using malloc() to allocate their memory (at least not directly???), so will free() work to deallocate/release the memory?

No -- new and malloc aren't guaranteed to use the same underlying system for allocating memory, so if you allocate with one system and try to free with the other, that will cause undefined behavior. If you use new you must use delete, and if you use malloc you must use free.

Tobias Dammers
Member #2,604
August 2002
avatar

In fact, if you're using C++ and not C, use new and delete whenever you can, which is practically everywhere - don't touch malloc and free at all. Only if you really really have to, and in that case, never mix the two systems. Ever.

Of course, when dealing with external C libraries such as allegro, read the manual carefully about how you are supposed to use data structures defined by them. It is very common for such libraries to provide special functions for creating and destroying objects (à la create_bitmap() / destroy_bitmap()). C++ libraries generally assume that you will be using new / delete on the objects they define.

BTW, the difference between new / delete and malloc / free is not only that they aren't guaranteed to use the same underlying mechanism.
New calls an object's constructor right after allocating the memory, and delete calls its destructor right before deallocating the memory, while malloc only allocates memory, but leaves it up to the programmer to initialize it to something useful, and free really only frees the memory, but doesn't do any other kind of cleanup.
C doesn't have constructors / destructors, which is why there are functions such as create_bitmap().

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

Go to: