C++ memory problem(bad alloc/segfault)???

Started by
3 comments, last by ToohrVyk 16 years, 1 month ago
Hi I have been trying to create a high(er) level wrapper for OpenGL, but I think there is something wrong with my code, though I am not experienced to spot it. I think I am doing something wrong with new/delete, but due to my lack of experience I do not know what. It has always given either a segfault or a bad alloc since I put in Button and rectangle2d. Here is the entire and unabridged code I have been working on: +----------+ |"Second.h"| +----------+

#include <iostream>
#include <stdio.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <SDL/SDL.h>

using namespace std;

struct rectangle2d
{
	float x1,y1,x2,y2,x3,y3,x4,y4;
	float r1,r2,r3,r4,g1,g2,g3,g4,b1,b2,b3,b4;
	void Set(int ind,float y,float x,float r,float g,float b)
	{
		switch(ind)
		{
			case 1:
			x1=x;
			y1=y;
			r1=r;
			g1=g;
			b1=b;
			break;
			case 2:
			x2=x;
			y2=y;
			r2=r;
			g2=g;
			b2=b;
			break;
			case 3:
			x3=x;
			y3=y;
			r3=r;
			g3=g;
			b3=b;
			break;
			case 4:
			x4=x;
			y4=y;
			r4=r;
			g4=g;
			b4=b;
			break;
		}
	}
	void operator=(rectangle2d rect)
	{
		x1=rect.x1;
		x2=rect.x2;
		x3=rect.x3;
		x4=rect.x4;
		y1=rect.y1;
		y2=rect.y2;
		y3=rect.y3;
		y4=rect.y4;
		r1=rect.r1;
		r2=rect.r2;
		r3=rect.r3;
		r4=rect.r4;
		g1=rect.g1;
		g2=rect.g2;
		g3=rect.g3;
		g4=rect.g4;
		b1=rect.b1;
		b2=rect.b2;
		b3=rect.b3;
		b4=rect.b4;
	}
};
struct triangle
{
	float x1;
	float x2;
	float x3;
	float y1;
	float y2;
	float y3;
	float z1;
	float z2;
	float z3;
	float r1,r2,r3,g1,g2,g3,b1,b2,b3;
	bool set;
	void Set(int ind,float x,float y,float z,float r,float g,float b)
	{
		switch(ind)
		{
			case 1:
			x1=x;
			y1=y;
			z1=z;
			r1=r;
			g1=g;
			b1=b;
			break;
			case 2:
			x2=x;
			y2=y;
			z2=z;
			r2=r;
			g2=g;
			b2=b;
			break;
			case 3:
			x3=x;
			y3=y;
			z3=z;
			r3=r;
			g3=g;
			b3=b;
			break;
		}
		set=true;
	}
	void operator=(triangle atri)
	{
		x1=atri.x1;
		x2=atri.x2;
		x3=atri.x3;
		y1=atri.y1;
		y2=atri.y2;
		y3=atri.y3;
		z1=atri.z1;
		z2=atri.z2;
		z3=atri.z3;
		r1=atri.r1;
		r2=atri.r2;
		r3=atri.r3;
		g1=atri.g1;
		g2=atri.g2;
		g3=atri.g3;
		b1=atri.b1;
		b2=atri.b2;
		b3=atri.b3;
	}
};
struct rectangle
{
	float x1,x2,x3,x4,y1,y2,y3,y4,z1,z2,z3,z4;
	float r1,r2,r3,r4,g1,g2,g3,g4,b1,b2,b3,b4;
	void Set(int ver,float x,float y,float z,float r,float g,float b)
	{
		switch(ver)
		{
			case 1:
			x1=x;
			y1=y;
			z1=z;
			r1=r;
			g1=g;
			b1=b;
			break;
			case 2:
			x2=x;
			y2=y;
			z2=z;
			r2=r;
			g2=g;
			b2=b;
			break;
			case 3:
			x3=x;
			y3=y;
			z3=z;
			r3=r;
			g3=g;
			b3=b;
			break;
			case 4:
			x4=x;
			y4=y;
			z4=z;
			r4=r;
			g4=g;
			b4=b;
			break;
		}
	}
	void operator=(rectangle rect)
	{
		x1=rect.x1;
		x2=rect.x2;
		x3=rect.x3;
		x4=rect.x4;
		y1=rect.y1;
		y2=rect.y2;
		y3=rect.y3;
		y4=rect.y4;
		z1=rect.z1;
		z2=rect.z2;
		z3=rect.z3;
		z4=rect.z4;
		r1=rect.r1;
		r2=rect.r2;
		r3=rect.r3;
		r4=rect.r4;
		g1=rect.g1;
		g2=rect.g2;
		g3=rect.g3;
		g4=rect.g4;
		b1=rect.b1;
		b2=rect.b2;
		b3=rect.b3;
		b4=rect.b4;
	}
};
struct API_COM1
{
	triangle* mesh;
	rectangle* bmesh;
	int tri;
	int rect;
	float tx,ty,tz;
	float ax,ay,az;
	void operator=(API_COM1 com)
	{
		if(mesh!=NULL)
		{
			delete mesh;
		}
		if(bmesh!=NULL)
		{
			delete bmesh;
		}
		mesh=com.mesh;
		bmesh=com.bmesh;
		rect=com.rect;
		tri=com.tri;
		tx=com.tx;
		ty=com.ty;
		tz=com.tz;
		ax=com.ax;
		ay=com.ay;
		az=com.az;
	}
};
struct API_COM2
{
	rectangle2d* rmesh;
	int rect;
	void operator=(API_COM2 com)
	{
		rect=com.rect;
		rmesh=com.rmesh;
	}
};

class API
{
	public:
	SDL_Surface* window;
	API_COM1* com1;
	API_COM2* com2;
	int com1_count;
	int com2_count;
	void Init(int x,int y,int z)
	{
		com1_count=0;
		com1=new API_COM1[com1_count];
		com2_count=0;
		com2=new API_COM2[com2_count];
		int vid;
		const SDL_VideoInfo* vinf;
		SDL_Init(SDL_INIT_VIDEO);
		vinf=SDL_GetVideoInfo();
		vid=SDL_OPENGL;
		vid|=SDL_GL_DOUBLEBUFFER;
		vid|=SDL_HWPALETTE;
		if(vinf->hw_available)
		{
			vid|=SDL_HWSURFACE;
		}else
		{
			vid|=SDL_SWSURFACE;
		}
		if(vinf->blit_hw)
		{
			vid|=SDL_HWACCEL;
		}
		SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);
		window=SDL_SetVideoMode(x,y,z,vid);
		glShadeModel(GL_SMOOTH);
		glClearColor(0.0f,0.0f,0.5f,0.0f);
		glClearDepth(5.0f);
		glEnable(GL_DEPTH_TEST);
		glDepthFunc(GL_LEQUAL);
		glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
		glViewport(0,0,(GLsizei)x,(GLsizei)y);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		if(y==0)
		{
			y=1;
		}
		gluPerspective(45.0f,x/y,0.1f,100.0f);
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
	}
	void Render()
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glLoadIdentity();
		for(int i=0;i<com1_count;i++)
		{
			glLoadIdentity();
			glTranslatef(com1.tx,com1.ty,com1.tz);
			glRotatef(com1.ax,1.0f,0.0f,0.0f);
			glRotatef(com1.ay,0.0f,1.0f,0.0f);
			glRotatef(com1.az,0.0f,0.0f,1.0f);
			for(int j=0;j<com1.tri;j++)
			{
				glBegin(GL_TRIANGLES);
				glColor3f(com1.mesh[j].r1,com1.mesh[j].g1,com1.mesh[j].b1);
				glVertex3f(com1.mesh[j].x1,com1.mesh[j].y1,com1.mesh[j].z1);
				glColor3f(com1.mesh[j].r2,com1.mesh[j].g2,com1.mesh[j].b2);
				glVertex3f(com1.mesh[j].x2,com1.mesh[j].y2,com1.mesh[j].z2);
				glColor3f(com1.mesh[j].r3,com1.mesh[j].g3,com1.mesh[j].b3);
				glVertex3f(com1.mesh[j].x3,com1.mesh[j].y3,com1.mesh[j].z3);
				glEnd();
			}
			for(int j=0;j<com1.rect;j++)
			{
				glBegin(GL_QUADS);
				glColor3f(com1.bmesh[j].r1,com1.bmesh[j].g1,com1.bmesh[j].b1);
				glVertex3f(com1.bmesh[j].x1,com1.bmesh[j].y1,com1.bmesh[j].z1);
				glColor3f(com1.bmesh[j].r2,com1.bmesh[j].g2,com1.bmesh[j].b2);
				glVertex3f(com1.bmesh[j].x2,com1.bmesh[j].y2,com1.bmesh[j].z2);
				glColor3f(com1.bmesh[j].r3,com1.bmesh[j].g3,com1.bmesh[j].b3);
				glVertex3f(com1.bmesh[j].x3,com1.bmesh[j].y3,com1.bmesh[j].z3);
				glColor3f(com1.bmesh[j].r4,com1.bmesh[j].g4,com1.bmesh[j].b4);
				glVertex3f(com1.bmesh[j].x4,com1.bmesh[j].y4,com1.bmesh[j].z4);
				glEnd();
			}
			glLoadIdentity();
		}
		for(int i=0;i<com2_count;i++)
		{
			glLoadIdentity();
			for(int j=0;j<com2.rect;j++)
			{
				glBegin(GL_QUADS);
				glColor3f(com2.rmesh[j].r1,com2.rmesh[j].g1,com2.rmesh[j].b1);
				glVertex2f(com2.rmesh[j].x1,com2.rmesh[j].y1);
				glColor3f(com2.rmesh[j].r2,com2.rmesh[j].g2,com2.rmesh[j].b2);
				glVertex2f(com2.rmesh[j].x2,com2.rmesh[j].y2);
				glColor3f(com2.rmesh[j].r3,com2.rmesh[j].g3,com2.rmesh[j].b3);
				glVertex2f(com2.rmesh[j].x3,com2.rmesh[j].y3);
				glColor3f(com2.rmesh[j].r4,com2.rmesh[j].g4,com2.rmesh[j].b4);
				glVertex2f(com2.rmesh[j].x4,com2.rmesh[j].y4);
				glEnd();
			}
		}
		glLoadIdentity();
		//Insert camera rotation/translation here!
		glFlush();
		SDL_GL_SwapBuffers();
	}
	void Shutdown()
	{
		SDL_Quit();
		delete com1->mesh;
		delete com1->bmesh;
		delete com2->rmesh;
		delete com1;
		delete com2;
	}
	void Wait(int time)
	{
		SDL_Delay(time);
	}
};

class EventScanner
{
	public:
	SDL_Event event;
	bool QUIT;
	bool KEY_UP;
	bool KEY_DOWN;
	bool KEY_LEFT;
	bool KEY_RIGHT;
	int MOUSE_X;
	int MOUSE_Y;
	bool MOUSE_LEFT;
	bool MOUSE_RIGHT;
	bool MOUSE_MOVE;
	EventScanner()
	{
		QUIT=false;
		KEY_UP=false;
		KEY_DOWN=false;
		KEY_LEFT=false;
		KEY_RIGHT=false;
		int MOUSE_X=0;
		int MOUSE_Y=0;
		bool MOUSE_MOVE=false;
		MOUSE_LEFT=false;
		MOUSE_RIGHT=false;
	}
	void Scan()
	{
		MOUSE_MOVE=false;
		while(SDL_PollEvent(&event))
		{
			switch(event.type)
			{
				case SDL_QUIT:
				QUIT=true;
				break;
				case SDL_KEYDOWN:
				switch(event.key.keysym.sym)
				{
					case SDLK_UP:
					KEY_UP=true;
					break;
					case SDLK_DOWN:
					KEY_DOWN=true;
					break;
					case SDLK_LEFT:
					KEY_LEFT=true;
					break;
					case SDLK_RIGHT:
					KEY_RIGHT=true;
					break;
				}
				break;
				case SDL_KEYUP:
				switch(event.key.keysym.sym)
				{
					case SDLK_UP:
					KEY_UP=false;
					break;
					case SDLK_DOWN:
					KEY_DOWN=false;
					break;
					case SDLK_LEFT:
					KEY_LEFT=false;
					break;
					case SDLK_RIGHT:
					KEY_RIGHT=false;
					break;
				}
				break;
				case SDL_MOUSEMOTION:
				MOUSE_MOVE=true;
				MOUSE_X=event.motion.x;
				MOUSE_Y=event.motion.y;
				break;
				case SDL_MOUSEBUTTONDOWN:
				switch(event.button.button)
				{
					case SDL_BUTTON_LEFT:
					MOUSE_LEFT=true;
					break;
					case SDL_BUTTON_RIGHT:
					MOUSE_RIGHT=true;
					break;
				}
				break;
				case SDL_MOUSEBUTTONUP:
				switch(event.button.button)
				{
					case SDL_BUTTON_LEFT:
					MOUSE_LEFT=false;
					break;
					case SDL_BUTTON_RIGHT:
					MOUSE_RIGHT=false;
					break;
				}
				break;
			}
		}
	}
};

class GL_Object
{
	public:
	API* api;
	int index;
	void Register(API* api2)
	{
		API_COM1* temp;
		temp=new API_COM1[api->com1_count];
		index=0;
		api=api2;
		for(int i=0;i<api->com1_count;i++)
		{
			temp=api->com1;
			index++;
		}
		delete api->com1;
		api->com1_count++;
		api->com1=new API_COM1[api->com1_count];
		for(int i=0;i<(api->com1_count-1);i++)
		{
			api->com1=temp;
		}
		delete temp;
		api->com1[index].tri=0;
		api->com1[index].rect=0;
		api->com1[index].mesh=new triangle[api->com1[index].tri];
		api->com1[index].bmesh=new rectangle[api->com1[index].rect];
		api->com1[index].ax=0.0f;
		api->com1[index].ay=0.0f;
		api->com1[index].az=0.0f;
		api->com1[index].tx=0.0f;
		api->com1[index].ty=0.0f;
		api->com1[index].tz=0.0f;
	}
	void Add(triangle tri)
	{
		int ind=0;
		triangle* temp=new triangle[api->com1[index].tri];
		for(int i=0;i<api->com1[index].tri;i++)
		{
			temp=api->com1[index].mesh;
			ind++;
		}
		delete api->com1[index].mesh;
		api->com1[index].tri++;
		api->com1[index].mesh=new triangle[api->com1[index].tri];
		for(int i=0;i<(api->com1[index].tri-1);i++)
		{
			api->com1[index].mesh=temp;
		}
		delete temp;
		api->com1[index].mesh[ind]=tri;
	}
	void Add(rectangle tri)
	{
		int ind=0;
		rectangle* temp=new rectangle[api->com1[index].rect];
		for(int i=0;i<api->com1[index].rect;i++)
		{
			temp=api->com1[index].bmesh;
			ind++;
		}
		delete api->com1[index].bmesh;
		api->com1[index].rect++;
		api->com1[index].bmesh=new rectangle[api->com1[index].rect];
		for(int i=0;i<(api->com1[index].rect-1);i++)
		{
			api->com1[index].bmesh=temp;
		}
		delete temp;
		api->com1[index].bmesh[ind]=tri;
	}
	void Rotate(float x,float y,float z)
	{
		api->com1[index].ax=x;
		api->com1[index].ay=y;
		api->com1[index].az=z;
	}
	void Position(float x,float y,float z)
	{
		api->com1[index].tx=x;
		api->com1[index].ty=y;
		api->com1[index].tz=z;
	}
	void Clear()
	{
		
	}
};

class Button
{
	public:
	API* api;
};

API* InitAPI()
{
	API* api;
	api=new API;
	return api;
}
void ShutdownAPI(API* api)
{
	delete api;
}

+--------------------+ |"Second-attempt.cpp"| +--------------------+

#include <iostream>
#include "Second.h"

using namespace std;

float rot;
float rotx;
float posx;
bool ffleft;
GL_Object object;
GL_Object obj2;
EventScanner event;
triangle tri1;
triangle tri2;
rectangle rect1;
rectangle rect2;
rectangle rect3;

int main()
{
	API* api=InitAPI();
	tri1.Set(1,-1.0f,0.0f,0.0f,1.0f,0.0f,0.0f);
	tri1.Set(2,0.0f,1.0f,0.0f,0.0f,1.0f,0.0f);
	tri1.Set(3,1.0f,0.0f,0.0f,0.0f,0.0f,1.0f);
	tri2.Set(1,-1.0f,0.0f,-2.0f,1.0f,0.0f,0.0f);
	tri2.Set(2,0.0f,1.0f,-2.0f,0.0f,1.0f,0.0f);
	tri2.Set(3,1.0f,0.0f,-2.0f,0.0f,0.0f,1.0f);
	rect1.Set(1,-1.0f,0.0f,0.0f,1.0f,0.0f,0.0f);
	rect1.Set(2,-1.0f,0.0f,-2.0f,1.0f,0.0f,0.0f);
	rect1.Set(3,1.0f,0.0f,-2.0f,0.0f,0.0f,1.0f);
	rect1.Set(4,1.0f,0.0f,0.0f,0.0f,0.0f,1.0f);
	rect2.Set(1,0.0f,1.0f,0.0f,0.0f,1.0f,0.0f);
	rect2.Set(2,0.0f,1.0f,-2.0f,0.0f,1.0f,0.0f);
	rect2.Set(3,1.0f,0.0f,-2.0f,0.0f,0.0f,1.0f);
	rect2.Set(4,1.0f,0.0f,0.0f,0.0f,0.0f,1.0f);
	rect3.Set(1,-1.0f,0.0f,0.0f,1.0f,0.0f,0.0f);
	rect3.Set(2,-1.0f,0.0f,-2.0f,1.0f,0.0f,0.0f);
	rect3.Set(3,0.0f,1.0f,-2.0f,0.0f,1.0f,0.0f);
	rect3.Set(4,0.0f,1.0f,0.0f,0.0f,1.0f,0.0f);
	api->Init(500,500,32);
	object.Register(api);
	object.Position(0.0f,-1.0f,-10.0f);
	object.Add(tri1);
	object.Add(tri2);
	object.Add(rect1);
	object.Add(rect2);
	object.Add(rect3);
	event.Scan();
	rot=0.0f;
	rotx=0.0f;
	posx=0.0f;
	ffleft=false;
	while(event.QUIT==false)
	{
		object.Position(posx,-1.0f,-10.0f);
		object.Rotate(rotx,rot,0.0f);
		api->Render();
		rot=rot+1.0f;
		rotx=rotx+0.5f;
		if(posx<-2.0)
		{
			ffleft=false;
		}
		if(posx>2.0)
		{
			ffleft=true;
		}
		if(ffleft==true)
		{
			posx=posx-0.01f;
		}
		if(ffleft==false)
		{
			posx=posx+0.01f;
		}
		event.Scan();
	}
	api->Shutdown();
	ShutdownAPI(api);
}

+------------+
|"compile.sh"|
+------------+

g++ Second-attempt.cpp -c -oSecond-attempt.o
cc `sdl-config --cflags` `sdl-config --libs` -lm -L/usr/X11R6/lib -lGL -lGLU -oSecond-attempt Second-attempt.o

NOTE: When I declare my variables globally in Second-attemp.cpp, it gives a segfault but if I declare the inside main() it gives a bad alloc. NOTE 2: I use Linux/g++ -F [Edited by - SecondAttempt2 on March 2, 2008 10:09:11 AM]
Advertisement
I would take a look at it, but this formatting kills my eyes ;) Maybe you can edit your post and put the code between [source]
[/source] tags. It would also be nice if you could keep the code indented (I assume you indented it properly in your project.) Repasting it between source tags should preserve the indentation.

Edit:

Having said that, I think I spotted one place where you go wrong in your API class, the init function:
com1_count=0;com1=new API_COM1[com1_count];com2_count=0;com2=new API_COM2[com2_count];
You are creating a new array of 0 elements. Yet later you reference to elements within this array. You should make the size of the array at least 1 if you're going to try accessing it later. In any case, this is like telling the computer: "Hey, I would like you to allocate some memory for me. To be exact, I need 0 bytes of memory..."
Why would that take effect, seeing as it ran fine before with that line?
I'll check.
Thanks!

EDIT:
Oh,well. It didn't. the segfault and bad alloc are still there.

#include <iostream>#include <stdio.h>#include <GL/gl.h>#include <GL/glu.h>#include <SDL/SDL.h>using namespace std;struct rectangle2d{	float x1,y1,x2,y2,x3,y3,x4,y4;	float r1,r2,r3,r4,g1,g2,g3,g4,b1,b2,b3,b4;	void Set(int ind,float y,float x,float r,float g,float b)	{		switch(ind)		{			case 1:			x1=x;			y1=y;			r1=r;			g1=g;			b1=b;			break;			case 2:			x2=x;			y2=y;			r2=r;			g2=g;			b2=b;			break;			case 3:			x3=x;			y3=y;			r3=r;			g3=g;			b3=b;			break;			case 4:			x4=x;			y4=y;			r4=r;			g4=g;			b4=b;			break;		}	}	void operator=(rectangle2d rect)	{		x1=rect.x1;		x2=rect.x2;		x3=rect.x3;		x4=rect.x4;		y1=rect.y1;		y2=rect.y2;		y3=rect.y3;		y4=rect.y4;		r1=rect.r1;		r2=rect.r2;		r3=rect.r3;		r4=rect.r4;		g1=rect.g1;		g2=rect.g2;		g3=rect.g3;		g4=rect.g4;		b1=rect.b1;		b2=rect.b2;		b3=rect.b3;		b4=rect.b4;	}};struct triangle{	float x1;	float x2;	float x3;	float y1;	float y2;	float y3;	float z1;	float z2;	float z3;	float r1,r2,r3,g1,g2,g3,b1,b2,b3;	bool set;	void Set(int ind,float x,float y,float z,float r,float g,float b)	{		switch(ind)		{			case 1:			x1=x;			y1=y;			z1=z;			r1=r;			g1=g;			b1=b;			break;			case 2:			x2=x;			y2=y;			z2=z;			r2=r;			g2=g;			b2=b;			break;			case 3:			x3=x;			y3=y;			z3=z;			r3=r;			g3=g;			b3=b;			break;		}		set=true;	}	void operator=(triangle atri)	{		x1=atri.x1;		x2=atri.x2;		x3=atri.x3;		y1=atri.y1;		y2=atri.y2;		y3=atri.y3;		z1=atri.z1;		z2=atri.z2;		z3=atri.z3;		r1=atri.r1;		r2=atri.r2;		r3=atri.r3;		g1=atri.g1;		g2=atri.g2;		g3=atri.g3;		b1=atri.b1;		b2=atri.b2;		b3=atri.b3;	}};struct rectangle{	float x1,x2,x3,x4,y1,y2,y3,y4,z1,z2,z3,z4;	float r1,r2,r3,r4,g1,g2,g3,g4,b1,b2,b3,b4;	void Set(int ver,float x,float y,float z,float r,float g,float b)	{		switch(ver)		{			case 1:			x1=x;			y1=y;			z1=z;			r1=r;			g1=g;			b1=b;			break;			case 2:			x2=x;			y2=y;			z2=z;			r2=r;			g2=g;			b2=b;			break;			case 3:			x3=x;			y3=y;			z3=z;			r3=r;			g3=g;			b3=b;			break;			case 4:			x4=x;			y4=y;			z4=z;			r4=r;			g4=g;			b4=b;			break;		}	}	void operator=(rectangle rect)	{		x1=rect.x1;		x2=rect.x2;		x3=rect.x3;		x4=rect.x4;		y1=rect.y1;		y2=rect.y2;		y3=rect.y3;		y4=rect.y4;		z1=rect.z1;		z2=rect.z2;		z3=rect.z3;		z4=rect.z4;		r1=rect.r1;		r2=rect.r2;		r3=rect.r3;		r4=rect.r4;		g1=rect.g1;		g2=rect.g2;		g3=rect.g3;		g4=rect.g4;		b1=rect.b1;		b2=rect.b2;		b3=rect.b3;		b4=rect.b4;	}};struct API_COM1{	triangle* mesh;	rectangle* bmesh;	int tri;	int rect;	float tx,ty,tz;	float ax,ay,az;	bool in1;	bool in2;	API_COM1()	{		in1=false;		in2=false;	}	void operator=(API_COM1 com)	{		if(mesh!=NULL)		{			delete mesh;		}		if(bmesh!=NULL)		{			delete bmesh;		}		mesh=com.mesh;		bmesh=com.bmesh;		rect=com.rect;		tri=com.tri;		tx=com.tx;		ty=com.ty;		tz=com.tz;		ax=com.ax;		ay=com.ay;		az=com.az;		in1=com.in1;		in2=com.in2;	}};struct API_COM2{	rectangle2d* rmesh;	int rect;	void operator=(API_COM2 com)	{		rect=com.rect;		rmesh=com.rmesh;	}};class API{	public:	SDL_Surface* window;	API_COM1* com1;	API_COM2* com2;	int com1_count;	int com2_count;	bool in1;	bool in2;	void Init(int x,int y,int z)	{		in1=false;		in2=false;		com1_count=1;		com1=new API_COM1[com1_count];		com2_count=1;		com2=new API_COM2[com2_count];		int vid;		const SDL_VideoInfo* vinf;		SDL_Init(SDL_INIT_VIDEO);		vinf=SDL_GetVideoInfo();		vid=SDL_OPENGL;		vid|=SDL_GL_DOUBLEBUFFER;		vid|=SDL_HWPALETTE;		if(vinf->hw_available)		{			vid|=SDL_HWSURFACE;		}else		{			vid|=SDL_SWSURFACE;		}		if(vinf->blit_hw)		{			vid|=SDL_HWACCEL;		}		SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);		window=SDL_SetVideoMode(x,y,z,vid);		glShadeModel(GL_SMOOTH);		glClearColor(0.0f,0.0f,0.5f,0.0f);		glClearDepth(5.0f);		glEnable(GL_DEPTH_TEST);		glDepthFunc(GL_LEQUAL);		glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);		glViewport(0,0,(GLsizei)x,(GLsizei)y);		glMatrixMode(GL_PROJECTION);		glLoadIdentity();		if(y==0)		{			y=1;		}		gluPerspective(45.0f,x/y,0.1f,100.0f);		glMatrixMode(GL_MODELVIEW);		glLoadIdentity();	}	void Render()	{		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		glLoadIdentity();		for(int i=0;i<com1_count;i++)		{			glLoadIdentity();			glTranslatef(com1.tx,com1.ty,com1.tz);			glRotatef(com1.ax,1.0f,0.0f,0.0f);			glRotatef(com1.ay,0.0f,1.0f,0.0f);			glRotatef(com1.az,0.0f,0.0f,1.0f);			for(int j=0;j<com1.tri;j++)			{				glBegin(GL_TRIANGLES);				glColor3f(com1.mesh[j].r1,com1.mesh[j].g1,com1.mesh[j].b1);				glVertex3f(com1.mesh[j].x1,com1.mesh[j].y1,com1.mesh[j].z1);				glColor3f(com1.mesh[j].r2,com1.mesh[j].g2,com1.mesh[j].b2);				glVertex3f(com1.mesh[j].x2,com1.mesh[j].y2,com1.mesh[j].z2);				glColor3f(com1.mesh[j].r3,com1.mesh[j].g3,com1.mesh[j].b3);				glVertex3f(com1.mesh[j].x3,com1.mesh[j].y3,com1.mesh[j].z3);				glEnd();			}			for(int j=0;j<com1.rect;j++)			{				glBegin(GL_QUADS);				glColor3f(com1.bmesh[j].r1,com1.bmesh[j].g1,com1.bmesh[j].b1);				glVertex3f(com1.bmesh[j].x1,com1.bmesh[j].y1,com1.bmesh[j].z1);				glColor3f(com1.bmesh[j].r2,com1.bmesh[j].g2,com1.bmesh[j].b2);				glVertex3f(com1.bmesh[j].x2,com1.bmesh[j].y2,com1.bmesh[j].z2);				glColor3f(com1.bmesh[j].r3,com1.bmesh[j].g3,com1.bmesh[j].b3);				glVertex3f(com1.bmesh[j].x3,com1.bmesh[j].y3,com1.bmesh[j].z3);				glColor3f(com1.bmesh[j].r4,com1.bmesh[j].g4,com1.bmesh[j].b4);				glVertex3f(com1.bmesh[j].x4,com1.bmesh[j].y4,com1.bmesh[j].z4);				glEnd();			}			glLoadIdentity();		}		for(int i=0;i<com2_count;i++)		{			glLoadIdentity();			for(int j=0;j<com2.rect;j++)			{				glBegin(GL_QUADS);				glColor3f(com2.rmesh[j].r1,com2.rmesh[j].g1,com2.rmesh[j].b1);				glVertex2f(com2.rmesh[j].x1,com2.rmesh[j].y1);				glColor3f(com2.rmesh[j].r2,com2.rmesh[j].g2,com2.rmesh[j].b2);				glVertex2f(com2.rmesh[j].x2,com2.rmesh[j].y2);				glColor3f(com2.rmesh[j].r3,com2.rmesh[j].g3,com2.rmesh[j].b3);				glVertex2f(com2.rmesh[j].x3,com2.rmesh[j].y3);				glColor3f(com2.rmesh[j].r4,com2.rmesh[j].g4,com2.rmesh[j].b4);				glVertex2f(com2.rmesh[j].x4,com2.rmesh[j].y4);				glEnd();			}		}		glLoadIdentity();		//Insert camera rotation/translation here!		glFlush();		SDL_GL_SwapBuffers();	}	void Shutdown()	{		SDL_Quit();		delete com1->mesh;		delete com1->bmesh;		delete com2->rmesh;		delete com1;		delete com2;	}	void Wait(int time)	{		SDL_Delay(time);	}};class EventScanner{	public:	SDL_Event event;	bool QUIT;	bool KEY_UP;	bool KEY_DOWN;	bool KEY_LEFT;	bool KEY_RIGHT;	int MOUSE_X;	int MOUSE_Y;	bool MOUSE_LEFT;	bool MOUSE_RIGHT;	bool MOUSE_MOVE;	EventScanner()	{		QUIT=false;		KEY_UP=false;		KEY_DOWN=false;		KEY_LEFT=false;		KEY_RIGHT=false;		int MOUSE_X=0;		int MOUSE_Y=0;		bool MOUSE_MOVE=false;		MOUSE_LEFT=false;		MOUSE_RIGHT=false;	}	void Scan()	{		MOUSE_MOVE=false;		while(SDL_PollEvent(&event))		{			switch(event.type)			{				case SDL_QUIT:				QUIT=true;				break;				case SDL_KEYDOWN:				switch(event.key.keysym.sym)				{					case SDLK_UP:					KEY_UP=true;					break;					case SDLK_DOWN:					KEY_DOWN=true;					break;					case SDLK_LEFT:					KEY_LEFT=true;					break;					case SDLK_RIGHT:					KEY_RIGHT=true;					break;				}				break;				case SDL_KEYUP:				switch(event.key.keysym.sym)				{					case SDLK_UP:					KEY_UP=false;					break;					case SDLK_DOWN:					KEY_DOWN=false;					break;					case SDLK_LEFT:					KEY_LEFT=false;					break;					case SDLK_RIGHT:					KEY_RIGHT=false;					break;				}				break;				case SDL_MOUSEMOTION:				MOUSE_MOVE=true;				MOUSE_X=event.motion.x;				MOUSE_Y=event.motion.y;				break;				case SDL_MOUSEBUTTONDOWN:				switch(event.button.button)				{					case SDL_BUTTON_LEFT:					MOUSE_LEFT=true;					break;					case SDL_BUTTON_RIGHT:					MOUSE_RIGHT=true;					break;				}				break;				case SDL_MOUSEBUTTONUP:				switch(event.button.button)				{					case SDL_BUTTON_LEFT:					MOUSE_LEFT=false;					break;					case SDL_BUTTON_RIGHT:					MOUSE_RIGHT=false;					break;				}				break;			}		}	}};class GL_Object{	public:	API* api;	int index;	void Register(API* api2)	{		API_COM1* temp;		if(api->in1==true)		{			temp=new API_COM1[api->com1_count];			index=0;			api=api2;			for(int i=0;i<api->com1_count;i++)			{				temp=api->com1;				index++;			}			delete api->com1;			api->com1_count++;			api->com1=new API_COM1[api->com1_count];			for(int i=0;i<(api->com1_count-1);i++)			{				api->com1=temp;			}			delete temp;		}else		{			index=1;			api->in1=true;		}		api->com1[index].tri=1;		api->com1[index].rect=1;		api->com1[index].mesh=new triangle[api->com1[index].tri];		api->com1[index].bmesh=new rectangle[api->com1[index].rect];		api->com1[index].ax=0.0f;		api->com1[index].ay=0.0f;		api->com1[index].az=0.0f;		api->com1[index].tx=0.0f;		api->com1[index].ty=0.0f;		api->com1[index].tz=0.0f;	}	void Add(triangle tri)	{		int ind=0;		if(api->com1[index].in1==true)		{			triangle* temp=new triangle[api->com1[index].tri];			for(int i=0;i<api->com1[index].tri;i++)			{				temp=api->com1[index].mesh;				ind++;			}			delete api->com1[index].mesh;			api->com1[index].tri++;			api->com1[index].mesh=new triangle[api->com1[index].tri];			for(int i=0;i<(api->com1[index].tri-1);i++)			{				api->com1[index].mesh=temp;			}			delete temp;		}else		{			ind=1;			api->com1[index].in1=true;		}		api->com1[index].mesh[ind]=tri;	}	void Add(rectangle tri)	{		int ind=0;		if(api->com1[index].in2==true)		{			rectangle* temp=new rectangle[api->com1[index].rect];			for(int i=0;i<api->com1[index].rect;i++)			{				temp=api->com1[index].bmesh;				ind++;			}			delete api->com1[index].bmesh;			api->com1[index].rect++;			api->com1[index].bmesh=new rectangle[api->com1[index].rect];			for(int i=0;i<(api->com1[index].rect-1);i++)			{				api->com1[index].bmesh=temp;			}			delete temp;		}else		{			ind=1;			api->com1[index].in2=true;		}		api->com1[index].bmesh[ind]=tri;	}	void Rotate(float x,float y,float z)	{		api->com1[index].ax=x;		api->com1[index].ay=y;		api->com1[index].az=z;	}	void Position(float x,float y,float z)	{		api->com1[index].tx=x;		api->com1[index].ty=y;		api->com1[index].tz=z;	}	void Clear()	{			}};class Button{	public:	API* api;};API* InitAPI(){	API* api;	api=new API;	return api;}void ShutdownAPI(API* api){	delete api;}


-F

[Edited by - SecondAttempt2 on March 2, 2008 10:51:40 AM]
Alright, I really don't know where to start... so I'll just go through it from top to bottom :P

First, in your API_COM1 struct, I see you delete both mesh and bmesh:
void operator=(API_COM1 com){if(mesh!=NULL){delete mesh;}if(bmesh!=NULL){delete bmesh;}
Now, this already assumes a great deal, because suppose you had multiple instances of API_COM1 referring to the same mesh. Then you could no longer use a mesh that may still be used in other instances. However, assuming you will only ever have only one instance of API_COM1 this is not yet detrimental.
At the same time it's strange however, that in the API_COM2 struct you do not delete mesh and bmesh.

Then, in the API class you do the following in your init function:
void Init(int x,int y,int z){	com1_count=0;	com1=new API_COM1[com1_count];	com2_count=0;	com2=new API_COM2[com2_count];}
You request memory for a dynamic array with 0 items here. I have no idea if that is even possible, but if it is, it is extremely dangerous because you may not refer to it (after all, there's nothing in it).

I took a look at your secondattempt.h file and noticed you call the GLObject.Register function right after the API.init function, and I noticed you're doing exactly the same thing in there:
API_COM1* temp;temp=new API_COM1[api->com1_count];index=0;api=api2;for(int i=0;i<api->com1_count;i++){	temp=api->com1;	index++;}delete api->com1;
As you can see, you request 0 bytes of memory again and then you go into a loop while it is perfectly clear that the code inside the loop can NEVER be executed because the com1_count value is 0 (which, in this case saves you from another possible place for a segmentation fault).

Right after this, I see:
api->com1_count++;api->com1=new API_COM1[api->com1_count];for(int i=0;i<(api->com1_count-1);i++){	api->com1=temp;}delete temp;
Again, you don't get into the loop at all, because you decrease api->com1_count by one and 1-1 is 0. In this case, it is lucky that the code inside the loop doesn't get executed, because temp is another array with 0 elements. Suppose you ran through the loop once; it would have caused a segmentation fault.

Walking through your code this way, I get the impression that you are under the impression that every element of a dynamically created array needs to be initialized with a 'new' statement. This is not true. You only use 'new' once, at the creation of your array, and usually you'll create enough space for it to hold whatever you'll want to put inside it. In any case, you should never use 'new' to create arrays with 0 elements.

There are a number of other instances where you use new and delete rather freely , but I have not checked them all. Judging by this code, I'd really have to say it would be good if you spent some more time learning C++ before venturing into the exciting world of graphics. It may sound harsh, but you'll thank yourself for it later. The code shows that you aren't aware of many very basic elements of the language, and that is a prerequisite before you start on frameworks like these.

I hope you will take this as constructive criticism as that's really all I meant with it ;)

Regards,

Rogier
Holy crap. Do you realize how much work you've done for nothing ?

For starters, here are your rectangle and triangle types. I have added GL-related functions to them so that they're easier to use.

struct point2d {   float x, y;   point2d(float x, float y) : x(x), y(y) {}  void gl() const { glVertex2f(x,y); }};struct point3d {   float x, y, z;   point3d(float x, float y, float z) : x(x), y(y), z(z) {}  void gl() const { glVertex3f(x,y,z); }};struct color {   float r, g, b;   color(float r, float g, float b) : r(r), g(g), b(b) {}  void gl() const { glColor3f(r,g,b); }}template<typename Point, int N>struct polygon{  Point vertices[N];  color colors[N];  void set(unsigned i, const Point &p, const color &c)  {    assert (i < N);    vertices = p;    colors = c;  }  void gl() const  {    for (int i = 0; i < N; ++i)    {       vertices.gl();      colors.gl();    }  }  // copy constructor is implemented by the compiler automatically.  // operator= is implemented by the compiler automatically.};typedef polygon<point2d,4> rectangle2d;typedef polygon<point3d,3> triangle;typedef polygon<point3d,4> rectangle;template<typename T> void gl(const T & t) { t.gl(); }



Then, there's your API_COM1, which contains several errors:

struct API_COM1 // What does that name mean?{triangle* mesh; // Use 'std::vector' !rectangle* bmesh;int tri; int rect;float tx,ty,tz; // Use 'point3d' !float ax,ay,az;void operator=(API_COM1 com) // Pass argument by reference!{if(mesh!=NULL) // You can delete null pointers!{delete mesh; // Do you really own this pointer?}if(bmesh!=NULL){delete bmesh;}mesh=com.mesh; // What if you assign an object to itself?bmesh=com.bmesh;rect=com.rect;tri=com.tri;tx=com.tx;ty=com.ty;tz=com.tz;ax=com.ax;ay=com.ay;az=com.az;}};


And the corrected version, including GL rendering.

struct mesh3d{  std::vector&lt;triangle&gt; tris;  std::vector&lt;rectangle&gt; quads;  point3d angle, position;  void gl() const  {    const point3d & a = angle, & t = position;    glLoadIdentity();    glTranslatef(t.x, t.y, t.z);    glRotatef(a.x,1.0f,0.0f,0.0f);    glRotatef(a.y,0.0f,1.0f,0.0f);    glRotatef(a.z,0.0f,0.0f,1.0f);    glBegin(GL_TRIANGLES);    std::for_each(tris.begin(), tris.end(), gl);    glEnd();    glBegin(GL_QUADS);    std::for_each(quads.begin(), quads.end(), gl);    glEnd();  }  // operator= and copy constructor are automatically  // implemented.};std::vector&lt;rectangle2d&gt; mesh2d;void gl(const mesh2d &m){  glLoadIdentity();  glBegin(GL_QUADS);  std::for_each(m.begin(), m.end(), gl);  glEnd();}


Of course, this is completely ignoring any design issues you have here, for instance the complete lack of encapsulation, or the fact that you are designing objects in terms of "what data they contain" instead of "how they are used and what they do".

Then, there's the issue of your main API class...

class API{  SQL_Surface *window;public:  std::vector<mesh3d> meshes3d;  std::vector<mesh2d> meshes2d;  API(int w, int h, int depth)   {    meshes3d.resize(10000);    meshes2d.resize(1000);    if (h == 0) h = 1;    SDL_Init(SDL_INIT_VIDEO);    try {        const SDL_VideoInfo* vinf = SDL_GetVideoInfo();      const int vid =         SDL_OPENGL |         SDL_GL_DOUBLEBUFFER |        SDL_HWPALETTE |        (vinf -> hwavailable ? SDL_HWSURFACE : SDL_SWSURFACE) |         (vinf -> blit_hw ? SDL_HWACCEL : 0);        this->window = SDL_SetVideoMode(h,w,depth,vid);        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);      glShadeModel(GL_SMOOTH);      glClearColor(0.0f,0.0f,0.5f,0.0f);      glClearDepth(5.0f);      glEnable(GL_DEPTH_TEST);      glDepthFunc(GL_LEQUAL);      glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);      glViewport(0,0,(GLsizei)h,(GLsizei)w);      glMatrixMode(GL_PROJECTION);      glLoadIdentity();      gluPerspective(45.0f,(float)x/(float)y,0.1f,100.0f);      glMatrixMode(GL_MODELVIEW);      glLoadIdentity();    } catch(...) {          SQL_Quit();      throw;     }  }  ~API() { SDL_QUIT(); }  void render() const  {    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    glLoadIdentity();    std::for_each(meshes3d.begin(), meshes3d.end(), gl);    std::for_each(meshes2d.begin(), meshes2d.end(), gl);    glFlush();    SDL_GL_SwapBuffers();  }};


I've forcibly moved "waiting" out of there. Plus, I have added no error-checking.

struct EventScanner{  bool QUIT,        KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT,        MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MOVE;  struct { int x, y } MOUSE;  EventScanner()  {    QUIT =     KEY_UP = KEY_DOWN = KEY_LEFT = KEY_RIGHT =     MOUSE_LEFT = MOUSE_RIGHT = MOUSE_MOVE = false;    MOUSE.x = MOUSE.y = 0;  }  void scan()  {    MOUSE_MOVE = false;    SDL_Event event;    bool down;    while (SDL_PollEvent(&event))    {       switch (event.type)       {      case SDL_QUIT: QUIT = true; break;      case SDL_KEYDOWN:      case SDL_KEYUP:        down = (event.type == SDL_KEYDOWN);        switch (event.key.keysym.sym)        {        case SDLK_UP: KEY_UP = down; break;        case SDLK_DOWN: KEY_DOWN = down; break;        case SDLK_LEFT: KEY_LEFT = down; break;        case SDLK_RIGHT: KEY_RIGHT = down; break;        }        break;      case SDL_MOUSEMOTION:        MOUSE_MOVE = true;        MOUSE.x = event.motion.x;        MOUSE.y = event.motion.y;        break;      case SDL_MOUSEBUTTONDOWN:      case SDL_MOUSEBUTTONUP:        down = (event.type == SDL_MOUSEBUTTONDOWN);        switch(event.button.button)        {        case SDL_BUTTON_LEFT: MOUSE_LEFT = down; break;        case SDL_BUTTON_RIGHT: MOUSE_RIGHT = down; break;        }        break;         default: break;      }    }  }};


I've factored similar cases using a "down" boolean variable, and also used chain assignment. You could consider using an integer point2d to represent the mouse position, or convert it to floating-point.

When your source gets to "GL_Object", things are starting to get confused. There's a lot of work being done that is completely useless (such as reinventing std::vector several times), objects not being destroyed properly, temporary values, confusions between buffers and single pointed objects, and so on, and I wonder if you actually know, yourself, what the code is meant to do. Though, I'll use:

class mesh3d_ref {  API & api;  index i;public:  mesh3d_ref(API & api, unsigned index) : api(api), i(index) {}  mesh3d* operator ->() { return &api.meshes3d; }};


Of course, this is suboptimal (how do you handle object removal?) but I'm not trying to write an entire engine here.

Which brings us to the test file:

int main(){   API api(500,500,32);     api.meshes3d.resize(1);  mesh3d_ref mesh(api, 0);  triangle t1 =   { { { -1f, 0f, 0f }, {  0f, 1f, 0f }, {  1f, 0f, 0f } },    { {  1f, 0f, 0f }, {  0f, 1f, 0f }, {  0f, 0f, 1f } } };  triangle t2 =  { { { -1f, 0f, -2f }, {  0f, 1f, -2f }, {  1f, 0f, -2f } },    { {  1f, 0f,  0f }, {  0f, 1f,  0f }, {  0f, 0f,  1f } } };  mesh -> tris.push_back(t1);  mesh -> tris.push_back(t2);  rectangle r1 =   { { { -1f,0f,0f }, { -1f,0f,-2f }, { 1f,0f,-2f }, { 1f,0f,0f } },    { {  1f,0f,0f }, {  1f,0f, 0f }, { 0f,0f, 1f }, { 0f,0f,1f } } };    rectangle r2 =   { { { 0f,1f,0f }, { 0f,1f,-2f }, { 1f,0f,-2f }, { 1f,0f,0f } },    { { 0f,1f,0f }, { 0f,1f, 0f }, { 0f,0f, 1f }, { 0f,0f,1f } } };  rectangle r3 =   { { { -1f,0f,0f }, { -1f,0f,-2f }, { 0f,1f,-2f }, { 0f,1f,0f } },    { {  1f,0f,0f }, {  1f,0f, 0f }, { 0f,1f, 0f }, { 0f,1f,0f } } };  mesh -> quads.push_back(r1);  mesh -> quads.push_back(r2);  mesh -> quads.push_back(r3);  EventScanner scanner;  float rot = 0f, rotx = 0f, pos = 0f, dpos = -0.01;  do   {    mesh -> position = point3d(pos, -0.1f, -10.0f);    mesh -> angle = point3d(rotx, rot, 0.0f);    rot += 1f;    rotx += 0.5f;    pos += dpos;    dpos = (pos < -2f) ?  0.01f :            (pos >  2f) ? -0.01f : dpos;    api.render();    event.scan();  }  while (!event.QUIT);  }


Please note that this code contains exactly zero instances of 'new' and 'delete'.

This topic is closed to new replies.

Advertisement