I am not sure why but this code (an attampt at a point and click game engine using Allegro 5) throws up an unhandled exception. The program starts and displays a picture, but as soon as the mouse is moved the exception pops up and the program crashes. I have highlighted the line (154) the IDE points to when it pops the exception message.

Any ideas on why would be greatly appreciated. I've been thinking about this all day and can't find the problem :(

// Adventure.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <allegro5/allegro.h>
#include <allegro5/allegro5.h>
#include <allegro5/allegro_image.h>
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_ttf.h>
#include <allegro5/allegro_audio.h>
#include <allegro5/allegro_acodec.h>
#include <iostream>
#include "string.h"
#include <windows.h>

using namespace std;

ALLEGRO_DISPLAY *display = NULL;
ALLEGRO_BITMAP *screenBitmapBuffer;
ALLEGRO_EVENT ev;
ALLEGRO_EVENT_QUEUE* event_queue = NULL;

class hotspot
{
private:
	string pairedScreen;
	string link;
public:
	int a,b,c,d;

	hotspot(string link, int a, int b, int c, int d)
	{
		this->link = link;
		this->a = a;
		this->b = b;
		this->c = c;
		this->d = d;
	}
};

class screen
{
private:

	ALLEGRO_BITMAP* imageStatic;
	hotspot* hotspots[8];

public:

	screen(const char* imageStatic)
	{
		this->imageStatic = al_load_bitmap(imageStatic);
	    this->hotspots[1] = new hotspot("test2",0,0,100,100);
		this->hotspots[2] = NULL;
		this->hotspots[3] = NULL;
		this->hotspots[4] = NULL;
		this->hotspots[5] = NULL;
		this->hotspots[6] = NULL;
		this->hotspots[7] = NULL;
		this->hotspots[8] = NULL;

	}
	screen()
	{
		this->imageStatic = NULL;
	}
	void display()
	{
		cout << this->imageStatic << endl;
		al_draw_bitmap(this->imageStatic,0,0,0);
		al_flip_display();
	}
	void setBitmap(const char* filename)
	{
		this->imageStatic = al_load_bitmap(filename);
	}
	hotspot* checkHotspot(int x)
	{
		return hotspots[x];
	}
		
};

void loadBitmapToScreen(screen* x, const char* filename)
{
	screenBitmapBuffer = al_load_bitmap(filename);
	if(screenBitmapBuffer)
	{
			x->setBitmap(filename);
			al_destroy_bitmap(screenBitmapBuffer);
	}
	else
	{
		cout << "Failed to load bitmap!" << endl;
	}

}

bool mouseWithin(hotspot* hot, int x, int y)
{
	cout << hot->a << endl;
	cout << hot->d << endl;

	//hotspot* hotCheck = hot;
	if(x > hot->a && x < hot->d && y > hot->a && y < hot->d)
	{
		
		return true;
	}
	else
	{

		return false;
	}
}

void initEngine()
{
    al_init();
    al_init_image_addon();
	al_init_font_addon();
	al_init_ttf_addon();
	al_install_audio();
	al_init_acodec_addon();
	al_install_mouse();
	display = al_create_display(500, 500);
	al_set_target_bitmap(al_get_backbuffer(display));
	if(!display)
	{
		cout << "Fatal Error: Unable to create display" << endl;
	}
}

int main(int argc, char** argv)
{
	initEngine();
	screen* Test = new screen();
	loadBitmapToScreen(Test, "Images\\01-ahead.png");
	Test->display();
	cout << "Hello World" << endl;
	al_set_new_display_flags(ALLEGRO_NOFRAME);

	event_queue = al_create_event_queue();
	al_register_event_source(event_queue, al_get_mouse_event_source());

	while(true)
	{
	al_wait_for_event(event_queue, &ev);

    if(ev.type == ALLEGRO_EVENT_MOUSE_AXES)
	{
		//system("cls");
	THIS LINE  -->	if(mouseWithin(Test->checkHotspot(1),ev.mouse.x,ev.mouse.y) == true)
		{
			cout << "mouse is within hotspot" << endl;
		}
		else
		{
			cout << "No hotspot" << endl;
		}
		//int gay = Test->checkHotspot(1)->a;
		cout << "X:" << ev.mouse.x << " Y:" << ev.mouse.y << endl;
		//
	}
	}
	system("PAUSE");
	return 0;
}

Dani AI

Generated

Quick summary tying the thread together: correctly suspected a null pointer, and / correctly flagged array/index problems. Below are focused, practical fixes and a small modern-C++ pattern to avoid the same crash and similar bugs going forward.

Prefer a container that expresses size and ownership (no raw new/raw array). Example: use a fixed-size vector of smart pointers so elements start out empty and are safe to check:

std::vector<std::unique_ptr<hotspot>> hotspots(8); // all elements nullptr initially
hotspots[0] = std::make_unique<hotspot>("test", 0, 0, 100, 100);

Always bounds-check and null-check before dereferencing. Make checkHotspot return nullptr for out-of-range indices, and change the event handler to grab the pointer first:

auto *h = Test->checkHotspot(i);
if (h && mouseWithin(h, ev.mouse.x, ev.mouse.y)) { ... }

Fix the hit-test logic so X uses left/right coordinates and Y uses top/bottom (the original used the same fields for both axes). A robust mouseWithin should also normalize bounds so a/c or b/d can be in any order:

bool mouseWithin(const hotspot* h, int x, int y) {
    if (!h) return false;
    int left = std::min(h->a,h->c), right = std::max(h->a,h->c);
    int top  = std::min(h->b,h->d), bottom= std::max(h->b,h->d);
    return x >= left && x <= right && y >= top && y <= bottom;
}

Additional tips: if sticking with manual allocation, implement destructor / rule-of-five or switch to RAII. Call Allegro display-configuration functions before creating the display (flags/settings apply at creation). For debugging, enable bounds checks, use the debugger to inspect pointers at breakpoints, and consider AddressSanitizer or the MSVC debug heap to catch invalid accesses early.

Recommended Answers

All 4 Replies

My guess is that the Test->checkHotspot(1) argument to mousewithin() is returning a null pointer.

Lines 54 to 61 are off by one. You should know that indices in C/C++ go from 0 to N-1, that is, for an array hotspot* hotspots[8]; , the indices should go from 0 to 7, not from 1 to 8. This is really basic stuff.

Your default constructor does not initialize the "hotspots" array. And, as rubberman said, this means that the Test->checkHotspot(1) call returns a NULL pointer. When it is dereferenced in the mousewithin() function, you get a crash (segmentation fault or Access Violation, depending on your OS).

Your "screen" class holds dynamically allocated memory, yet you don't have a destructor (and nor do you have a deep-copy constructor and assignment operator). That's an error, you have memory leaking, and possibly more problems down the line. Read my tutorial on RAII for details.

You may have other errors, but start by solving the above-mentioned issues.

commented: rightly directed +2

I agree with Mike's view, below code is exception prone:-

this->hotspots[8] = NULL;

Array limits works from 0 to n-1, where n is the size of array. keep this thing in mind. And you must also free all memory which got alloctaed dynamically.

Ah, dammit! It's always something so obvious! lol thanks guys. As for memory allocation and freeing memory, the code isn't finished yet, I'll be implementing that later :P

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.