Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

fireking

Class Problem (And Crash!)

This topic is 5940 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok, Ive got a problem with this code, But i just cannot figure out the problem, the program crashes as soon as its executed here is our main program
  

#include <windows.h>
#include "glob.h"

HWND hwnd;//store our hwnd, its used a lot

HDC dc;//store the dc so we can draw to the window whenever we want

glob g;

LRESULT CALLBACK WindowProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam);//defined window proc for handling the window's messages


int WINAPI WinMain(HINSTANCE h,HINSTANCE p,LPSTR cl,int sc){
	MSG *msg=new MSG;//create a new msg struct

	WNDCLASSEX w;//create a new wnd class

	w.cbClsExtra=0;//we dont need this

	w.cbSize=sizeof(w);//this is always the same

	w.cbWndExtra=0;//we dont need this

	w.hbrBackground=(HBRUSH)COLOR_WINDOW;//use the system default color of a window

	w.hCursor=LoadCursor(NULL,IDC_ARROW);//use a mouse arrow

	w.hIcon=LoadIcon(NULL,IDI_APPLICATION);//use the default application icon

	w.hIconSm=LoadIcon(NULL,IDI_APPLICATION);//use the default application icon

	w.hInstance=h;//pass the instance of this application

	w.lpfnWndProc=WindowProc;//set the window proc, defined above, written below

	w.lpszClassName="Glob2";//the class name we will use

	w.lpszMenuName=NULL;//there is no menu

	w.nostyle=CS_VREDRAW|CS_HREDRAW;//draw vertically and horizontally

	RegisterClassEx(&w);//register our class, dont forget to unregister ONLY IF you use RegisterClassEx

	hwnd=CreateWindow(
		"Glob2",//class name

		"My Window",//window title

		WS_SYSMENU|WS_MAXIMIZEBOX|WS_MINIMIZEBOX|WS_SIZEBOX,//style

		CW_USEDEFAULT,//use default x

		CW_USEDEFAULT,//use default y

		640,//width

		480,//height

		NULL,//not important

		NULL,//not important

		h,//instance of this application

		NULL);//not important

	if(!hwnd){//the window wasnt created, so dont attempt to do the stuff after this condition

		MessageBox(0,"Window cannot be created!","Error!",0);
		return 0;//quit this application

	}
	ShowWindow(hwnd,sc);//show the window

	UpdateWindow(hwnd);//update it

	SendMessage(hwnd,WM_PAINT,NULL,NULL);//manually paint the window//

	dc=GetDC(hwnd);//get our dc, dont forget to release the dc. 

	//You delete a dc if its a created dc (CreateCompatibleDC) 

	//you release a dc if its done by GetDC or if it pertains 

	//directly to a window

	g.add_red(g.x+rand()%25,g.y+rand()%25);
	//g.add_blue(g.next->x+rand()%25,g.next->y+rand()%25);

	//g.add_green(g.next->x+rand()%25,g.next->y+rand()%25);

	while(1){//message pump

		if(PeekMessage(msg,NULL,0,0,PM_REMOVE)){//peek message is commonly used for games

			if(msg->message==WM_QUIT) break;//if its quit, break this while loop

			TranslateMessage(msg);
			DispatchMessage(msg);
		}
		//run your game loop here, its your entry point to the application loop

		g.draw(dc);
		Sleep(10);
	}
	ReleaseDC(hwnd,dc);//release our dc

	UnregisterClass("Glob2",h);//unregister the class cuz we used RegisterClassEx


	return msg->wParam;//return this value

}
LRESULT CALLBACK WindowProc(HWND whwnd,UINT imsg,WPARAM wparam,LPARAM lparam){
	PAINTSTRUCT ps;//paint struct for painting routine

	switch(imsg){
	case WM_GETMINMAXINFO://this is used to specify how small or how big the window can go

		LPMINMAXINFO m;//our struct, dont forget its a pointer

		POINT p;//make a point struct

		m=(LPMINMAXINFO)lparam;//get the default info for the minmaxinfo struct

		p.x=352;//set our values in p to specify how small this window can be

		p.y=352;
		m->ptMinTrackSize=p;//set this value to specify how small the window can be

		//i didnt break or return because i think windows needs

		//to return a value, but im not sure what value

		//so i let defwindowproc do it


	case WM_PAINT://window needs to be repainted for various reasons

		BeginPaint(hwnd,&ps);//you dont have to do this, but i usually do

		//because i can put stuff in between here to modify the

		//paint of the window

		EndPaint(hwnd,&ps);
		return(0);//tell windows we handled it

		break;

	case WM_DESTROY://close button was clicked, or some application is trying to close this application

		PostQuitMessage(0);//quit the application (this just breaks the while loop actually)

		break;

	}
	return DefWindowProc(whwnd,imsg,wparam,lparam);//return the default window procedure

}

  
And here is the Glob class, and other classes inherited:
  

//glob.h


#include <windows.h>
class glob{
public:
	int x;
	int y;
	virtual void draw(HDC dc);
	void add(glob *g);
	void add_red(int xx,int yy);
	void add_blue(int xx,int yy);
	void add_green(int xx,int yy);
	glob *next;
};
class glob_red:Public glob{
public:
	void draw(HDC dc);
};
class glob_blue:Public glob{
public:
	void draw(HDC dc);
};
class glob_green:Public glob{
public:
	void draw(HDC dc);
};
//===========================

//glob.cpp

#include "glob.h"

void glob::draw(HDC dc){
	glob *gg;
	gg=this->next;
	while(gg!=NULL){
		gg->draw(dc);
		gg=gg->next;
	}
};
void glob::add(glob *g){
	glob *gg;
	gg=this;//our pointer points to the current glob

	while(gg->next!=NULL){//if the current glob's next isnt null

		gg=gg->next;//we set gg to the next one, cuz its not null,

		//and we need to find the first null next

		//note: changing gg only changes which glob gg points to

	}
	gg->next=g;//we have reached a null next, so set it to the parameter

}
void glob::add_red(int xx,int yy){
	glob_red gr;
	gr.x=xx;
	gr.y=yy;
	this->add(&gr);
}
void glob::add_green(int xx,int yy){
	glob_green gr;
	gr.x=xx;
	gr.y=yy;
	this->add(&gr);
}
void glob::add_blue(int xx,int yy){
	glob_blue gr;
	gr.x=xx;
	gr.y=yy;
	this->add(&gr);
}
void glob_red::draw(HDC dc){
	RECT r;
	HBRUSH brush;
	r.left=x-8;
	r.right=x+8;
	r.top=y-8;
	r.bottom=y+8;
	brush=CreateSolidBrush(RGB(255,0,0));
	FillRect(dc,&r,brush);
	DeleteObject(brush);
}
void glob_blue::draw(HDC dc){
	RECT r;
	HBRUSH brush;
	r.left=x-8;
	r.right=x+8;
	r.top=y-8;
	r.bottom=y+8;
	brush=CreateSolidBrush(RGB(0,0,255));
	FillRect(dc,&r,brush);
	DeleteObject(brush);
}
void glob_green::draw(HDC dc){
	RECT r;
	HBRUSH brush;
	r.left=x-8;
	r.right=x+8;
	r.top=y-8;
	r.bottom=y+8;
	brush=CreateSolidBrush(RGB(0,255,0));
	FillRect(dc,&r,brush);
	DeleteObject(brush);
}

  
I apologize for the length of code, but i cannot figure out the problem! Thanks! --Fireking Owner/Leader Genetics 3rd Dimension Development [edited by - fireking on September 12, 2002 9:34:02 PM] [edited by - fireking on September 12, 2002 9:35:58 PM]

Share this post


Link to post
Share on other sites
Advertisement
This might not be the source of the crash but this:

w.hbrBackground=(HBRUSH)COLOR_WINDOW;

should be

w.hbrBackground=(HBRUSH)(COLOR_WINDOW + 1);

oh and this - this looks like the likely culprit

MSG *msg=new MSG;//create a new msg struct

A regular auto variable should do the trick - just

MSG msg;

That also means changing

return msg->wParam

to just

return msg.wParam

and changing

PeekMessage(msg,NULL,0,0,PM_REMOVE)

to just

PeekMessage(&msg,NULL,0,0,PM_REMOVE)

Try that and see if it makes a difference.



Share this post


Link to post
Share on other sites
you cant have MSG msg, cuz it says the variable isnt initialized, hence the pointer

also, it crashes when i do g.add_red(blah blah);

hence why g.add_green and g.add_blue are commented out

--Fireking

Owner/Leader
Genetics 3rd Dimension Development

Share this post


Link to post
Share on other sites
ok nevermind, i just used MSG msg and it worked, but earlier it kept saying it wasnt intialized i swear...

ok anyways, it doesnt crash at g.add_red, it is atually crashing when it draws red, so whats wrong?

--Fireking

Owner/Leader
Genetics 3rd Dimension Development

Share this post


Link to post
Share on other sites
ok, ive found the actual problem


  

void glob::draw(HDC dc){
glob *gg;
MessageBox(0,"We are gonna draw","",0);
if(this->next==NULL) return;
gg=this->next;
while(gg!=NULL){
MessageBox(0,"
Loop","",0);
gg->draw(dc);
MessageBox(0,"
Draw","",0);
if(gg->next!=NULL)
gg=gg->next;
else
break;
}
}



It never gets to MessageBox(0,"Draw","",0);

So gg->draw(dc); isnt happening. Its a virtual function, where it calls the function of the inherited class, at least thats what is supposed to happen, but something isnt working right

i suspect that since in the glob class the *next pointer is declared as a glob. But I need to declare it as a glob, to be general enough to hold one of the inherited classes, glob_red, glob_blue, or glob_green

so i bet that its just trying to call the vitual draw function over and over again, and crashes

does anyone know how i can fix this or what i am doing wrong?

thanks,


--Fireking

Owner/Leader
Genetics 3rd Dimension Development

Share this post


Link to post
Share on other sites
Um, yes you can have MSG msg. The compiler message that says the variable isn''t initialized comes about most likely because of some way that the variable is being used elsewhere - like not taking the "address of" the variable in the call to PostMessage for example. Take a look at Oluseyi''s tut on window class wrappers for an example using MSG msg: The Window Class and the Application Message Pump. That''s not likely the source of the problem - it will work either way, but you don''t need to allocate that variable from the heap.

Ok - it''s helpful to know where the program crashes. I suspect that the crash might have something to do with the absence of any memory allocation for the next pointer used in the add method. Trace through the call to add_red. The glob_red is an auto variable - so it gets pushed on the stack - then it''s passed to the add method where ultimately this->next is set equal to it. Add returns to add_red which returns popping glob_red off the stack - kapow! At least it looks that way to me. You''ll probably need to "new" some memory for that pointer and later "delete" it.

By the way - did you get the "WinRay" email?

Share this post


Link to post
Share on other sites
ok i just read this info about polymorphism, which i guess is what im trying to accomplish

Here''s some basic rules of ABC''s

1) You CAN NOT declare an instance of an ABC. So for our example SHAPE is an ABC
(Abstract Base Class), I COULD NOT do the following:

int main()
{
SHAPE shape; // I could not do this, won''t compile

return 0;
}

* Facts about pure virtual functions:

1) They have the keyword "virtual" before the function
2) They are followed by "=0"
3) They have NO implementation
4) Any class that contains a pure virtual function, makes that class a
Abstract Base Class

*/

so i conclude, im not doing something right...

I am wanting to declare g as a glob, then put glob_red''s, glob_blue''s, and glob_green''s into glob, with a linked list. Then when i draw, it will walk through the linked list and call each class''s draw function. This is where it gets confusing, because the glob has to be general enough to hold either a glob_red, a glob_blue, OR a glob_green. Thats why its declared as glob, and glob_red, glob_blue, and glob_green are all childs to the parent class glob.

--Fireking

Owner/Leader
Genetics 3rd Dimension Development

Share this post


Link to post
Share on other sites
You''re moving pretty fast there fireking

A draw function isn''t the best place to put a message box - considering that draw will likely get called dozens of times per second. It never gets to MessageBox(0,"Draw","",0); because of the recursion - you''ve set up a long chain of calls to draw - and each call never gets the chance to return. At least it looks that way to my "C" eyes - which is to say that I have doubts as to whether that is the case in C++ - but I suspect that it is. To get around that, ditch the while loop inside draw. Consider how that works as it stands now - you have a while loop inside draw that calls draw that starts a while loop that calls draw that starts a while loop that calls draw ... and so on.

Is there a constructor for each glob type? If you might consider making brush a member of the class and putting this call

brush=CreateSolidBrush(RGB(0,0,255));

into the constructor and this call

DeleteObject(brush);

into the destructor - since that code never changes why go through the extra work of creating the brush every time through the function?

Share this post


Link to post
Share on other sites
Ok I see where you''re going - consider what is common to each of those glob types and what is not. They all have a brush, they all have coordinates, they all draw - basically they all to the same things, except that each of them has a different color. So - the part that should be specific to each of the derived classes is the part that sets it''s color.

To call each of them in a linked list, isolate the object part from the list. A list is a container - just a bucket. Leave the drawing part to each object and let the container deal with keeping track of all the objects. So in effect what you would have is something liek

getnextitemfromlist - itemdrawyourself
getnextitemfromlist - itemdrawyourself
getnextitemfromlist - itemdrawyourself
getnextitemfromlist - itemdrawyourself

and so on. The objects can keep track of themselves too - but at the least, isolate the getnextitem part from the draw part.


Share this post


Link to post
Share on other sites
i know that, but thats not the point

im trying to do something that would be complex, but simpler. Like someday, i will actually have to do this, make classes, with inherited classes, such as a game situation. I know i could simply just make one glob class, add more variables, and draw using those variables, but thats not what im trying to do. Im trying to do it with polymorphism and inheritance, thats the point of such a simple program...

also, i have my drawing in the while loop, the message boxes are there to FIND THE ERROR, i took them out after i found what line it was crashing on (debugging wouldnt find it).

so now i know that you CANT do what im trying to do with a ABC, and its a ABC if you have a virtual function, cuz if a class has a virtual function, it becomes an ABC. Hence the reason why i cannot do

glob g;

as a declaration, cuz ABC's can only be declared as pointers.

--Fireking

Owner/Leader
Genetics 3rd Dimension Development

[edited by - fireking on September 12, 2002 12:53:40 AM]

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!