c++ dynamisches array?

T

[theSparrow]

Gast
so ich verstehs einfach nicht und komm nicht dahinter:
Ich programmier grad Opengl und da hab ich folgendes:

Folgende Strukturen:
Code:
struct KOPOS
{
	float fx,fy,fz;
	float ftx,fty;
};

struct TRIANGLE
{
	KOPOS kopos[3];
	int iTex;
	float alpha;
	float r,g,b;
};

struct CIRCLE
{
	KOPOS kopos;
	float rad;
	int iTex;
	float alpha;
	float r,g,b;
};

struct CYLINDER
{
	KOPOS kopos;
	float inrad;
	float outrad;
	float length;
	int iTex;
	float alpha;
	float r,g,b;
};

struct SECTOR
{
	long lnumTriangle;
	long lnumCircle;
	long lnumCylinder;
	long lnumObjects;

	TRIANGLE *triangle;
	CIRCLE *circle;
	CYLINDER *cylinder;
	
};

dann wird das so initialisiert:
Code:
int lnumTriangle=2;
int lnumCircle=2;
int lnumCylinder=2;

sSector0.triangle= new TRIANGLE[lnumTriangle];
sSector0.circle= new CIRCLE[lnumCircle];
sSector0.cylinder= new CYLINDER[lnumCylinder];

und dann gibt es folgendes problem:
wenn ich dann die dreiecke usw. zeichnen will und auf die struktur zugreife wie folgt,
funktioniert es:
Code:
[...]
int i=0;

	
	for(i=0; i<sSector0.lnumTriangle; ++i)
	{
		float get=sSector0.triangle[i].r;
[...]

aber so:
Code:
[...]
int i=0;
float get=sSector0.triangle[i].r;
	
	for(i=0; i<sSector0.lnumTriangle; ++i)
	{
		
[...]
stürtzt das Programm ab!!!
Warum?
Ich kanns drehen und wenden wie ichs will es geht nicht?
Ich weiß echt nicht mehr weiter... wenn ich sofort statische arrays nim, funkt es normal, aber da ich die anzahl der arrays eigentlich aus einer datei lese sollten sie dynamisch sein aber es workt hintn und vorne nicht.
Was muss ich anders machen?

danke schonmal
mfg
 
Also ich bin auch nicht DER Pro was C++ betrifft, aber ich glaub ich hab einen Fehler.

Code:
int lnumTriangle=2;
int lnumCircle=2;
int lnumCylinder=2;

sSector0->triangle= new TRIANGLE[lnumTriangle];
sSector0->circle= new CIRCLE[lnumCircle];
sSector0->cylinder= new CYLINDER[lnumCylinder];
Es müsste doch eigendlich ein Pointer sein, wenn du was auf dem Heap reservierst.
(Oder täusch ich mich.)

Edit: Im übrigen würd ich die Variable i so lokal wie möglich halten, ich deklarier die immer erst im Schleifenkopf:

Code:
for (int i = 0; i<sSector0.lnumTriangle; ++i)
{
}
 
Zuletzt bearbeitet:
sSector0->triangle müsste sein, wenn sSector0 nen Pointer wär, isser aber nicht, deswegen sSector0.triangle.
und dass es mit ++i nicht geht wundert micht nicht. Es hatt schon einen Grund, dass es in C++ sowohl ++i als auch i++ gibt.
Wenn du z.B. for(int i=0; i<10; i++) schreibst, geht die Schleife von 0 bis 9, bei ++i geht sie von 1 bis 10.

//Edit: Konkret mein ich du musst for(i=0; i<sSector0.lnumTriangle; i++) benutzen, nur falls das nicht automatisch klar wird ;-)
 
hmm das mit i++ und ++i klang einleuchtend, leider funktioniert es immer noch nicht.
trotzdem danke!
Was könnte ich sonst noch versuchen?

edit: die schleife geht egal ob ich ++i oder i++ verwende immer von 0 weg...
 
Zuletzt bearbeitet:
@[theSparrow]
Sry, hast recht. War nen Denkfehler.
Der Unterschied ist nur bei ner direkten Zuweisung, z.B.
int a=5;
int b=a++;
a=5;
int c=++a;//b!=c

Ic glaub aber ich weiß, wo noch nen Problem sein könnte. Scheinbar hatt ja die Struktur sSector0 membervariablen lnumTriangle, lnumCircle und lnumCylinder.
Die verwendest du aber eigentlich erst in den schleifen, davor benutzt du nciht-member variablen mit dem gleichen namen. Könntes sein, das du die Member nie definierst?
 
im moment hab ichs so:
Code:
[...]

int inumTriangle;
int inumCircle;
int inumCylinder;

while(!feof(fObjects))
	{
		
		 buffer=fgetsN(fObjects);
		
		 sscanf(buffer,"NUMTRIANGLE %d\n",&inumTriangle);
		 sSector0.lnumTriangle=inumTriangle;

		 buffer=fgetsN(fObjects);
		 sscanf(buffer,"NUMCIRCLE %d\n",&inumCircle);
		 sSector0.lnumCircle=inumCircle;

		 buffer=fgetsN(fObjects);
		 sscanf(buffer,"NUMCYLINDER %d\n",&inumCylinder);
		 sSector0.lnumCylinder=inumCylinder;

		break;
				
	}

	sSector0.triangle= new TRIANGLE[inumTriangle];
	sSector0.circle= new CIRCLE[inumCircle];
	sSector0.cylinder= new CYLINDER[inumCylinder];
 
der fehler kommt eben vor der schleife, wenn ich auf die struktur zugreifen will, also auf die dynamisch deklarierten objecte:

unhandled exception in test1.exe: 0xC0000005: Access Violation
 
der wert ist völlig irrelevant... das array wird ja mit inumtriangle initialisiert, welches direkt aus der datei (richtig) gelesen wird.
der fehler muss aber irgendwo bei den geposteten stellen liegen, da es einwandfrei funktioniert, wenn ich einfach statische arrays nehme... :freak:
 
Kann aber nicht so ganz sein, da die geposteten Stellen korrekt aussehen auf den ersten Blick. Klingt eher nach nem Speicherüberschreiber beim Einlesen z.B. oder doppelter Freigabe o.Ä. . Aber wenn du auf Fragen meinst sie wären irrelevant, brauchst du dich auch nicht zu wundern wenn dir nicht geholfen wird.
 
also ich würd mal versuchen einen VECTOR, LIST oder einen MAP zu nehmen ... die sind dann auch wirklich dynamisch und du mist nichtmehr mit irgendwelchen pointern irgendwohin zeigen

gruß riod
 
@7H3 N4C3R
sry, so wars nicht gemeint...
Habs nun nochmal überprüft, aber an den werten kanns wirklich nicht liegen, ich hab auch versucht sie "fest" also fix einzutragen, keine besserung.

@riod
vector hab ich auch versucht, kommt immer dasselbe bei raus...

so vielleicht hilfts wenn ich mehr code zeige:

also wie gehabt die deklaration:
Code:
struct KOPOS
{
	float fx,fy,fz;
	float ftx,fty;
};

struct TRIANGLE
{
	KOPOS kopos[3];
	int iTex;
	float alpha;
	float r,g,b;
};

struct CIRCLE
{
	KOPOS kopos;
	float rad;
	int iTex;
	float alpha;
	float r,g,b;
};

struct CYLINDER
{
	KOPOS kopos;
	float inrad;
	float outrad;
	float length;
	int iTex;
	float alpha;
	float r,g,b;
};

struct SECTOR
{
	long lnumTriangle;
	long lnumCircle;
	long lnumCylinder;
	long lnumObjects;
	
	TRIANGLE *triangle;
	CIRCLE *circle;
	CYLINDER *cylinder;


};


SECTOR sSector0;
dann die funktion die die daten aus der datei liest(+extralesefunktion):
Code:
char* fgetsN(FILE* fFile)
{
	char* cbuffer=(char*)malloc(256);
	while(!feof(fFile))
	{
		fgets(cbuffer,255,fFile);
		if((cbuffer[0]!='\n')&&(cbuffer[0]!='/')&&(cbuffer[0]!=' '))
			return (char*)cbuffer;
	}
	
	return (char*)"_eof_";
	
}

GLvoid GL_Load_Objects()
{
	FILE* fObjects;
	fObjects = fopen("data\\model.txt", "r");
	char* buffer=(char*)malloc(256);
	char cObject[256];
	char cBitmapPathBuf[256];
	
	while(!feof(fObjects))
	{
		

		 buffer=fgetsN(fObjects);
		
		 sscanf(buffer,"NUMTRIANGLE %d\n",&inumTriangle);
		 sSector0.lnumTriangle=inumTriangle;
		
		 buffer=fgetsN(fObjects);
		 sscanf(buffer,"NUMCIRCLE %d\n",&inumCircle);
		 sSector0.lnumCircle=inumCircle;

		 

		 buffer=fgetsN(fObjects);
		 sscanf(buffer,"NUMCYLINDER %d\n",&inumCylinder);
		 sSector0.lnumCylinder=inumCylinder;

		 

		break;
				
	}

	sSector0.triangle= new TRIANGLE[inumTriangle];
	sSector0.circle= new CIRCLE[inumCircle];
	sSector0.cylinder= new CYLINDER[inumCylinder];
	
	
	int numtriangle=0;
	int numcircle=0;
	int numcylinder=0;

	sSector0.lnumObjects=sSector0.lnumTriangle+sSector0.lnumCircle+sSector0.lnumCylinder;

	while(!feof(fObjects))
	{
		
		 buffer=fgetsN(fObjects);
		
		 sscanf(buffer,"BITNUM %i",&bitnum);


		 for(int i=0; i<bitnum; i++)
		 {
			buffer=fgetsN(fObjects);
			sscanf(buffer,"BITTEX %s\n",&cBitmapPathBuf);
			strcpy(cBitmapPath[i],cBitmapPathBuf);
			
		 }
		

		break;
				
	}

	float fx,fy,fz;
	float ftx,fty;
	float r,g,b;
	float alpha;
	int itex;
	float rad,inrad,outrad,length;

	while(true)
	{
		buffer=fgetsN(fObjects);
		
		if(!strcmp(buffer,"_eof_"))
			break;

		strcpy(cObject,"");
		sscanf(buffer,"OBJECT %s\n",&cObject);
	
		if(!strcmp(cObject,"TRIANGLE"))
		{
			buffer=fgetsN(fObjects);
			sscanf(buffer,"TEX %i\n",&itex);
			sSector0.triangle[numtriangle].iTex=itex;

			buffer=fgetsN(fObjects);
			sscanf(buffer,"ALPHA %f\n",&alpha);
			sSector0.triangle[numtriangle].alpha=alpha;

			buffer=fgetsN(fObjects);
			sscanf(buffer,"RGB %f %f %f\n",&r,&g,&b);
			
			sSector0.triangle[numtriangle].r=r;
			sSector0.triangle[numtriangle].g=g;
			sSector0.triangle[numtriangle].b=b;

			
			
			for(int i=0; i<3; i++)
			{
				buffer=fgetsN(fObjects);
				sscanf(buffer, "%f %f %f %f %f", &fx, &fy, &fz, &ftx, &fty);
				sSector0.triangle[numtriangle].kopos[i].fx=fx;
				sSector0.triangle[numtriangle].kopos[i].fy=fy;
				sSector0.triangle[numtriangle].kopos[i].fz=fz;

				sSector0.triangle[numtriangle].kopos[i].ftx=ftx;
				sSector0.triangle[numtriangle].kopos[i].fty=fty;
			}

			numtriangle++;
			
			
		}
		else if(!strcmp(cObject,"CIRCLE"))
		{
			buffer=fgetsN(fObjects);
			sscanf(buffer,"TEX %i\n",&itex);
			sSector0.circle[numcircle].iTex=itex;

			buffer=fgetsN(fObjects);
			sscanf(buffer,"ALPHA %f\n",&alpha);
			sSector0.circle[numcircle].alpha=alpha;

			buffer=fgetsN(fObjects);
			sscanf(buffer,"RGB %f %f %f\n",&r,&g,&b);
			
			sSector0.circle[numcircle].r=r;
			sSector0.circle[numcircle].g=g;
			sSector0.circle[numcircle].b=b;

			buffer=fgetsN(fObjects);
			sscanf(buffer,"RAD %f\n",&rad);
			sSector0.circle[numcircle].rad=rad;

			buffer=fgetsN(fObjects);
			sscanf(buffer, "%f %f %f %f %f", &fx, &fy, &fz, &ftx, &fty);
			sSector0.circle[numcircle].kopos.fx=fx;
			sSector0.circle[numcircle].kopos.fy=fy;
			sSector0.circle[numcircle].kopos.fz=fz;

			sSector0.circle[numcircle].kopos.ftx=ftx;
			sSector0.circle[numcircle].kopos.fty=fty;
			

			numcircle++;	
			
		}
		else if(!strcmp(cObject,"CYLINDER"))
		{
			buffer=fgetsN(fObjects);
			sscanf(buffer,"TEX %i\n",&itex);
			sSector0.cylinder[numcylinder].iTex=itex;

			buffer=fgetsN(fObjects);
			sscanf(buffer,"ALPHA %f\n",&alpha);
			sSector0.cylinder[numcylinder].alpha=alpha;

			buffer=fgetsN(fObjects);
			sscanf(buffer,"RGB %f %f %f\n",&r,&g,&b);
			
			sSector0.cylinder[numcylinder].r=r;
			sSector0.cylinder[numcylinder].g=g;
			sSector0.cylinder[numcylinder].b=b;

			buffer=fgetsN(fObjects);
			sscanf(buffer,"INRAD %f\n",&inrad);
			sSector0.cylinder[numcylinder].inrad=inrad;

			buffer=fgetsN(fObjects);
			sscanf(buffer,"OUTRAD %f\n",&outrad);
			sSector0.cylinder[numcylinder].outrad=outrad;

			buffer=fgetsN(fObjects);
			sscanf(buffer,"LENGTH %f\n",&length);
			sSector0.cylinder[numcylinder].length=length;

			buffer=fgetsN(fObjects);
			sscanf(buffer, "%f %f %f %f %f", &fx, &fy, &fz, &ftx, &fty);
			sSector0.cylinder[numcylinder].kopos.fx;
			sSector0.cylinder[numcylinder].kopos.fy;
			sSector0.cylinder[numcylinder].kopos.fz;

			sSector0.cylinder[numcylinder].kopos.ftx;
			sSector0.cylinder[numcylinder].kopos.fty;
			

			numcylinder++;	
		}
		else
			break;
	
	}

	
	
	fclose(fObjects);

}

so und dann werden hier die listen erstellt:

Code:
GLvoid GL_Load_Lists()
{
	GL_Delete_Lists();
	GL_Reset();
	
	lListPos=glGenLists(sSector0.lnumObjects);
	lListRunner=lListPos;
	
	int i=0;
	GLfloat fpx,fpy,fpz,ftpx,ftpy,frad,finrad,foutrad,flength; 
	for(i=0; i<sSector0.lnumTriangle; i++)
	{
		glNewList(lListRunner,GL_COMPILE);
		glColor4f(sSector0.triangle[i].r,sSector0.triangle[i].g,sSector0.triangle[i].b,sSector0.triangle[i].alpha);
		if(sSector0.triangle[i].iTex>0)
		{
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, texture[sSector0.triangle[i].iTex]);
		}
		else
			glDisable(GL_TEXTURE_2D);
		  	
	 
  
		glBegin(GL_TRIANGLES);
		glNormal3f( 0.0f, 0.0f, 1.0f);
		for (int j=0; j<3; j++)
		{
				
				fpx = sSector0.triangle[i].kopos[j].fx;
				fpy = sSector0.triangle[i].kopos[j].fy;
				fpz = sSector0.triangle[i].kopos[j].fz;
				ftpx = sSector0.triangle[i].kopos[j].ftx;
				ftpy = sSector0.triangle[i].kopos[j].fty;
				glTexCoord2f(ftpx,ftpy); glVertex3f(fpx,fpy,fpz);
		
		
		}
		glEnd();
		glEndList();
		lListRunner++;
	}

	for(i=0; i<sSector0.lnumCircle; i++)
	{
		glNewList(lListRunner,GL_COMPILE);
		glColor4f(sSector0.circle[i].r,sSector0.circle[i].g,sSector0.circle[i].b,sSector0.circle[i].alpha);
		if(sSector0.circle[i].iTex>0)
		{
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, texture[sSector0.circle[i].iTex]);
		}
		else
			glDisable(GL_TEXTURE_2D);
		  	
		
		
		fpx = sSector0.circle[i].kopos.fx;
		fpy = sSector0.circle[i].kopos.fy;
		fpz = sSector0.circle[i].kopos.fz;
		ftpx = sSector0.circle[i].kopos.ftx;
		ftpy = sSector0.circle[i].kopos.fty;
		frad = sSector0.circle[i].rad;
		
		glTexCoord2f(ftpx,ftpy);
		glTranslatef(fpx,fpy,fpz);
		gluSphere(gluobjects,frad,32,32);
		
				
				
		glEndList();
		lListRunner++;
	}


	
	for(i=0; i<sSector0.lnumCylinder; i++)
	{
		glNewList(lListRunner,GL_COMPILE);
		glColor4f(sSector0.cylinder[i].r,sSector0.cylinder[i].g,sSector0.cylinder[i].b,sSector0.cylinder[i].alpha);
		if(sSector0.cylinder[i].iTex>0)
		{
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, texture[sSector0.cylinder[i].iTex]);
		}
		else
			glDisable(GL_TEXTURE_2D);
		  	
		
		
		fpx = sSector0.cylinder[i].kopos.fx;
		fpy = sSector0.cylinder[i].kopos.fy;
		fpz = sSector0.cylinder[i].kopos.fz;
		ftpx = sSector0.cylinder[i].kopos.ftx;
		ftpy = sSector0.cylinder[i].kopos.fty;
		finrad = sSector0.cylinder[i].inrad;
		foutrad = sSector0.cylinder[i].outrad;
		flength = sSector0.cylinder[i].length;
		
		glTexCoord2f(ftpx,ftpy);
		glTranslatef(fpx,fpy,fpz);
		gluCylinder(gluobjects,finrad,foutrad,flength,32,32);	
				
		glEndList();
		lListRunner++;
	}
	
	lListRunner=lListPos;
}

und hier ist die zeichenroutine:
Code:
GLvoid GL_Render_Scene()
{
		
	GL_Cls();
	GL_Reset();
	
	gluobjects=gluNewQuadric();
	gluQuadricNormals(gluobjects, GLU_SMOOTH);
	gluQuadricTexture(gluobjects, GL_TRUE);
	
	glPolygonMode(GL_BACK, GL_POLY_MODE);                     
	glPolygonMode(GL_FRONT, GL_POLY_MODE);
	
	
	glRotatef(ydrehwinkel,0,1,0);
	glRotatef(xdrehwinkel,1,0,0);

	GL_Set3DPos(xweg/iRunFactor-2.0f,yweg/iRunFactor+0.0f,zweg/iRunFactor-12.0f);     

	int i=0;
	
    // wenn dieser teil ausklammert ist, läuft es, wenn nicht, stürtzt es ab...
       glColor4f(sSector0.triangle[i].r,
                      sSector0.triangle[i].g,
                      sSector0.triangle[i].b,
                      sSector0.triangle[i].alpha);

   //
	for(i=lListPos; i<=sSector0.lnumObjects; i++)
	{
		glCallList(i);
	}
	

	

}
 
Zitat von [theSparrow]:
@7H3 N4C3R
sry, so wars nicht gemeint...
Habs nun nochmal überprüft, aber an den werten kanns wirklich nicht liegen, ich hab auch versucht sie "fest" also fix einzutragen, keine besserung.
Kein Problem. Ich weiß, dass solche "Billigfragen" blöd klingen, allerdings zeigt die Erfahrung dass die Fehler meist in den Teilen liegen die man für überprüft und funktionierend hält. Deshalb die Frage.


Erste Frage und die Wichtigste:
Die Definition von SECTOR sSector0; - wird das in einem Header definiert? Sind die anderen Funktionen dann über verschiedene Übersetzungseinheiten (cpp-Files) verteilt und inkludieren dann diesen Header?

In diesem Falle wäre der Fehler schon gefunden, da sSector 0 dann mehrfach definiert würde und in allen anderen außer der lesenden Übersetzungseinheit Datenmüll enthalten würde (Allerdings wäre das auch eine Verletzung der OneDefinitionRule, die zu Linker-Fehlern führen sollte).

Zitat von [theSparrow]:
dann die funktion die die daten aus der datei liest(+extralesefunktion):
Code:
char* fgetsN(FILE* fFile)
{
	char* cbuffer=(char*)malloc(256);
	while(!feof(fFile))
	{
		fgets(cbuffer,255,fFile);
		if((cbuffer[0]!='\n')&&(cbuffer[0]!='/')&&(cbuffer[0]!=' '))
			return (char*)cbuffer;
	}
	
	return (char*)"_eof_";
	
}
Diese Funktion enthält bereits einige Fehler kann zu deinem Absturz führen.

Zuerst, das Testen alleine mit feof ist immer unzureichend. Ein Test mit ferror ist nach jedem Lesevorgang Pflicht, der Test auf feof davor. Erst wenn kein ferror nach dem Lesen vorliegt, darfst du auf das Ergebnis zugreifen. Der Test auf feof nach dem Lesen wäre ein Fehler, da trotz des Laufens auf EOF noch Daten gelesen worden sein könnten. Im Falle eines Lesefehlers wäre der Inhalt von cbuffer undefiniert (und du müsstest ihn auch wieder über free freigeben (genauso wie im EOF Fall) um Speicherlöcher zu vermeiden).
Der Cast von "_eof_" in einen (char*) wird auch die Conversion of Death genannt (in C++), da du hier einfach das const Attribut von einem Literal entfernst. Wird dann auf diesen Speicher (der dann üblicherweise in einem Readonly-Bereich liegt) schreibend zugegriffen, erntest du undefiniertes Verhalten und das Programm raucht meistens ab. In C wie in C++ sehr heikler Code.

In GL_Load_Objects überprüfst du den Rückgabewert von sscanf nicht. In dem Fall, dass sscanf fehlschlägt (Datenfehler (z.B. keine Zahl)), ist der Inhalt der übergebenen Variable(n) die nicht gelesen werden konnten anschließend undefiniert und darf nicht verwendet werden. Beim Lesen der einzelnen Objekte besteht auch die Gefahr, dass du über das eine des reservierten Speicherbereichs hinweg schreibst, da keine Prüfung vorhanden ist, ob die reservierte Größe des Arrays bereits erreicht ist. Das kann sehr schnell zu dem Absturz führen. Da das undefiniertes Verhalten wäre, könnte es im Falle von statischen Arrays vielleicht irgendwas (sinnvolles) tun.
 
@7H3 N4C3R
vielen dank für deine umfangreiche antwort. ich hab jetzt alle funktionen + die sector variable in eine header datei gepackt, keine besserung... :(
PS: diese header wird nur einmal in main.cpp includiert (hab auch nur dieses .cpp-file, rest ist .h).

ich gebe dir voll und ganz recht, in meinen funktionen sind im moment noch überhaupt keine fehlerüberprüfungen... das kommt einfach daher, dass ich das ziemlich schnell geschrieben und mir einfach sicher war, dass die nötigen parameter richtig in dem file stehen. Ist aber sicherlich nicht gut so und werde ich bei gelegenheit auch ändern; da es aber im moment mit statischen variablen funktioniert könnten lesefehler auch ausgeschlossen werden.

Aber ist es wirklich so schlimm wenn ich "_eof_" zurückschicke? Da ich ja eigentlich nur einen "erkennungsnamen" brauche, damit GL_Load_Objects(); weiß wann abzubrechen ist...

Ach vielleicht sollte ich das projekt eineisen und einfach ganz von vorne beginnen :-) ich weiß einfach nicht wieso ich einmal drauf zugreifen kann und dann wieder nicht :-(

oder hast du oder sonst jemand noch eine idee, worans liegen könnte? ;)

vielen dank,
mfg
 
Hmm... schwierig, so mehr zu sagen. *kopfkratz* Unter welcher Plattform und mit welchem Compiler arbeitest du denn dort? Wenn du unter Linux bist, könntest du Valgrind drauf ansetzen.
 

Ähnliche Themen

Zurück
Top