Very wierd program behaviour - Compiler bugs?

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
Kojima
Posts: 275
Joined: Mon Jun 26, 2006 3:49 am

Very wierd program behaviour - Compiler bugs?

Post by Kojima »

Hi,

I'm experiencing very wierd behaviour in my C++ psp app. (Raptor)

For example if I do this,

Code: Select all

	
	ParticleEngine * pe = new ParticleEngine( NULL,1000 );
	
it runs fine. I can see my particles on screen and it does not crash.

But if I change it to this,

Code: Select all


         Texture *ftex = new Texture("flare.jpg",JPEG);
	ParticleEngine * pe = new ParticleEngine( ftex,1000 );
	
It crashes in the particle engine call.

But , and this is where it gets really wierd.. If I add two calls to my log system within the particleengine constructor, one at the top, and one at the bottom, trying to pinpoint where it crashes.
It no longer crashes. But now my framerate(A counter at the top of the screen) firmly stays at ZERO, and the screen is blank.

This is the second time this has happened. I added a terrain engine to raptor recently, and if I call it before loading a b3d, the b3d call fails and crashes. but when I added logger calls to the b3d load, it no longer crashes.

The result of this is an impossible to trace crash point.

Here's the full code to the demo as it crashes, it's very simple with very little logic.

Code: Select all

int main(int argc, char **argv) 
{	
	pspDebugScreenInit();

	InitRaptor();

	Joypad *joy = new Joypad;

	SetDefaultStyle( new GradientStyle );
	Display *sys = new Display(argc,argv);
	Pen *pen = new Pen;
	
 	Camera *vcam = Factory->ProduceCamera();
 
 	vcam->Position(0,40,-20);
 
	Renderer->_ActiveCam = vcam;
	vcam->PointAt(0,0,0);
	
	float bx,by;
	bx=0;
	by=0;
	glDisable( GL_CULL_FACE );

	Font *fnt = new Font("fnt1.bmp",32,32);
 	FontRenderer->SetActive( fnt );
 	FontRenderer->SetColor(1,1,1);
	char * yawtxt = NULL;
	char * angtxt = NULL;
	int mode;
	mode = m_play;
 	float cx,cy;
 	cx=0;
 	cy=0;
 float ex=0;


  u64 fp_lms;
  int fp_frms;
	int fp_fps;
	int fp_first = true;

	int lm = sceRamLeft();
	float frame=1;
	Logger->Log("Entering Main Loop.\n");
	Texture *ftex = new Texture("flare.jpg",JPEG);
	Logger->Log("Creating PE\n");
	ParticleEngine * pe = new ParticleEngine( ftex,1000 );
	
	Particle * ep = pe->Emit( 5,0,0,0,0,0 );
	pe->Emit( 3,-2,0,0,0,0 );
	pe->Emit( 7,-1,0,0,0,0 );
	vcam->Position( 0,20,0 );
	vcam->PointAt( 0,0,0 );
	Logger->Log("Entering Main Loop.\n");

 	while(1)
 
  {

  	for&#40;int i=0;i<10;i++&#41;
  	&#123;
  	pe->Emit&#40; 0,0,0,&#40; -5+rand&#40;&#41;%10 &#41; ,0,&#40;-5+rand&#40;&#41;%10&#41;  &#41;;
  	&#125;;	
  	pe->Update&#40;&#41;;
			
  
  		frame++;
  		if&#40;frame>199&#41; frame=1;

 		u64 ms = GetTick&#40;&#41;;
 		if&#40; &#40;ms<fp_lms&#41; || &#40;fp_first == true&#41; &#41;
 		&#123;
 			fp_fps = fp_frms;
 			fp_frms=0;
 			fp_lms=ms-1000;
 			fp_first = false;
 		&#125;
 		fp_frms++;
  	glClear&#40;GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT&#41;;	
		j
oy->Update&#40;&#41;;
 		
 		float xi,yi;
 		xi = joy->_x;
 		yi = joy->_y;
 		
 		if&#40;fabs&#40;xi&#41;>0.4&#41;
 		&#123;
 			cx+=xi;
 		&#125;
 		if&#40;fabs&#40;yi&#41;>0.4&#41;
 		&#123;
 			cy+=yi;
 		&#125;
 			
 	
 		if&#40;cy>360&#41; cy=0;
 	
 		Renderer->RenderScene&#40;&#41;; 	  
 	 		
 		Blend_Mask&#40;&#41;;
 		sys->Draw2D&#40;&#41;;
 		if&#40; !&#40;yawtxt == NULL &#41; &#41;
 		&#123;
 			free&#40; &#40;void *&#41;yawtxt &#41;;
 		&#125;
 		yawtxt = StringUtil->Num&#40; fp_fps &#41;;
 		FontRenderer->RenderText&#40;0,0,yawtxt&#41;;
 		Blend_Solid&#40;&#41;;

		if&#40;joy->_select==1&#41;
		&#123;
			CloseRaptor&#40;&#41;;
			sceKernelExitGame&#40;&#41;;
		&#125;
  	if&#40; joy->_rtrigger &#41;
  	&#123;
  		screenshot&#40;"mplay"&#41;;
  	&#125;
  	glutSwapBuffers&#40;&#41;;

  &#125;

  return &#40;0&#41;;
&#125;

And here's my makefile. In case anything I've done in that could be causing the strange behaviour.

Code: Select all

TARGET = lesson2
OBJS = main.o

CFLAGS = -G0 -Wall
CXXFLAGS = $&#40;CFLAGS&#41; -fno-exceptions 
ASFLAGS = $&#40;CFLAGS&#41;
	
PSPBIN = $&#40;PSPSDK&#41;/../bin
CFLAGS += -I$&#40;PSPSDK&#41;/../include  -fsingle-precision-constant -g  
LIBS +=  -llua -lz  -lpspgu -ljpeg -lpng -lz -losl -lpspgu -lmikmod -lpspaudio -lGLU -lglut -lGLU -lGL -llualib -llua -lm -lc -lpsputility -lpspdebug -lpspge -lpspdisplay -lpspctrl -lpspsdk -lpspvfpu -lpsplibc -lpspuser -lpspkernel -lpsprtc -lpsppower -lstdc++ -llua
LDFLAGS += -DMODULE_NAME="Raptor Alpha" psp-setup.c



EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = Raptor Test
# PSP_EBOOT_ICON = hero.png
# PSP_EBOOT_PIC1 = bg.png


PSPSDK=$&#40;shell psp-config --pspsdk-path&#41;
include $&#40;PSPSDK&#41;/lib/build.mak
If it makes a difference, I'm using the jun2nd build of xorloser prebuilt psp toolchain. with svn versions of pspgl,mikmok and lua.

Any help would be appreciated as this is just something I've never seen before. I've coded a million apps on the pc and never run into this before.
Kojima
Posts: 275
Joined: Mon Jun 26, 2006 3:49 am

Post by Kojima »

I just tried,

Code: Select all

	Texture *ftex = new Texture&#40;"flare.jpg",JPEG&#41;;
	Logger->Log&#40;"Creating PE\n"&#41;;
	ParticleEngine * pe = new ParticleEngine&#40; NULL,1000 &#41;;
	
Which loads the texture but does not assign, and now I see the particles again BUT they are all skewed and it's like an almost isometric view. (The camera is directlly above them)

I remove the load texture call and like magic it appears normal again.

It really cannot be the texture code causing this, as I've tried both bmp and jpg textures, both of which use different methods of loading.

So it could either be A) a compiler bug. B) a pspGL bug or C) human error.

I also tried various make file combinations, like o2 optimization, removing wall, removing just about every option one by one, but nothing made the slightest bit of difference.
Last edited by Kojima on Wed Aug 09, 2006 7:45 pm, edited 1 time in total.
danzel
Posts: 182
Joined: Fri Nov 04, 2005 11:03 pm

Post by danzel »

Me 2!

I had a function that read from a file character by character and did some pointer arithmetic to put it in a char* and it had a complete stop somewhere in there with no exceptions, when I added some debug printfs it started working.
In the end I made it use indexing instead of pointer arithmetic and it worked.
Strange times....

Maybe you could step through it with psplink/gdb to work out whats happening?
Kojima
Posts: 275
Joined: Mon Jun 26, 2006 3:49 am

Post by Kojima »

Ah if only, psplink doesn't work for me. I think because my pc has usb1.1 instead of 2.0.

So it could be pointers causing the problem huh? Have to admit I don't like the idea of replacing my pointers..In fact I don't even think I could, not without major major redesigns and going back to C which is just ugh..:)
User avatar
ReKleSS
Posts: 73
Joined: Sat Jun 18, 2005 12:57 pm
Location: Melbourne, Australia

Post by ReKleSS »

1) USB version makes no difference. USB 1.1 is 12Mbps; USB2 is 480Mbps (yeah right...). psplink will work.

2) Your error sounds like memory getting trampled on. Take a careful look around. You're probably overrunning an array or something.
Kojima
Posts: 275
Joined: Mon Jun 26, 2006 3:49 am

Post by Kojima »

Nah search the forums, there are quite a few cases of people with usb1.1 having problems with osolink.
I did try it, compiled all the pc side apps etc, but as soon as it connects it trashes the usb connection and I have to reboot the pc to use usb again.

As for overrunning an array etc, I doubt it as there are no arrays, so it leaves only malloced space. Which is probable but I have checked and found no problems.
I'll have another look to be sure though.
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

ReKless is most likely right. All my weird behaviour bugs I had up to now, resolved to me somewhere over/underrunning a buffer. Then only one totally different line in the code would change the crash behaviour completely.
So your buffer overrun could be in the texture loader, but doesn't need to. If you can't find it by yourself, probably try with the memory manager I already suggested somewhere here. It's also helpful to track buffer over/underruns, as it signs all allocated memory areas at beginning and end, so when these change you know which buffer was over/underrun.
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
Kojima
Posts: 275
Joined: Mon Jun 26, 2006 3:49 am

Post by Kojima »

You maybe right, although I managed to locate the source of the problem.
JPEG textures. I kludged my b3d loader to use the bmp loader when finding jpegs, and replaced zombie.jpg with a bmp by the same name, and now it works fine.

So it appears either the jpeg library is broken, or I've made a mistake in my loader.

Here it is, if anyone has experience with the loader I'd appreciate any pointers you may have.

Code: Select all


class JpgLoader
&#123;
public&#58;
	JpgLoader&#40;&#41;
	&#123;
	&#125;
	Img * LoadJpg&#40;const char *file&#41;
	&#123;
		struct jpeg_decompress_struct cinfo;
		struct my_error_mgr jerr;
  	/* More stuff */
	  FILE * infile;		/* source file */
 		JSAMPARRAY buffer;		/* Output row buffer */
	  int row_stride;		/* physical row width in output buffer */
  	if &#40;&#40;infile = fopen&#40;file, "rb"&#41;&#41; == NULL&#41; &#123;
  	  printf&#40;"Unable to load jpg %s\n", file&#41;;
  	  return NULL;
  	&#125;
  	cinfo.err = jpeg_std_error&#40;&jerr.pub&#41;;
	  jerr.pub.error_exit = my_error_exit;
	  /* Establish the setjmp return context for my_error_exit to use. */
	  if &#40;setjmp&#40;jerr.setjmp_buffer&#41;&#41; &#123;
	    /* If we get here, the JPEG code has signaled an error.
	     * We need to clean up the JPEG object, close the input file, and return.
	     */
	    jpeg_destroy_decompress&#40;&cinfo&#41;;
	    fclose&#40;infile&#41;;
	    return NULL;
	  &#125;
  	/* Now we can initialize the JPEG decompression object. */
 	   jpeg_create_decompress&#40;&cinfo&#41;;

  	/* Step 2&#58; specify data source &#40;eg, a file&#41; */
  	 jpeg_stdio_src&#40;&cinfo, infile&#41;;
			
		 &#40;void&#41; jpeg_read_header&#40;&cinfo, TRUE&#41;;
		 &#40;void&#41; jpeg_start_decompress&#40;&cinfo&#41;;
  	 row_stride = cinfo.output_width * cinfo.output_components;
  	   buffer = &#40;*cinfo.mem->alloc_sarray&#41;
		&#40;&#40;j_common_ptr&#41; &cinfo, JPOOL_IMAGE, row_stride, 1&#41;;
			char *imgbuf = &#40;char *&#41;memalign&#40;16, cinfo.output_width*cinfo.output_height * cinfo.output_components &#41;;
		
			_buf = imgbuf;
			_w = cinfo.output_width;
			_h = cinfo.output_height;
			_c = cinfo.output_components;
			_ln = 0;
			
		while &#40;cinfo.output_scanline < cinfo.output_height&#41; &#123;
    	/* jpeg_read_scanlines expects an array of pointers to scanlines.
    	 * Here the array is only one element long, but you could ask for
    	 * more than one scanline at a time if that's more convenient.
    	 */
    	&#40;void&#41; jpeg_read_scanlines&#40;&cinfo, buffer, 1&#41;;
    	/* Assume put_scanline_someplace wants a pointer and sample count. */
    	AddScan&#40;&#40;char *&#41;buffer&#91;0&#93;, row_stride&#41;;
    &#125;
    
    
  &#40;void&#41; jpeg_finish_decompress&#40;&cinfo&#41;;
     jpeg_destroy_decompress&#40;&cinfo&#41;;
       fclose&#40;infile&#41;;
    Img * img = new Img;
    img->_buf = _buf;
    img->_w = _w;
    img->_h = _h;
    img->_c = _c;
    return img;
    	 	 
	&#125;
	void AddScan&#40; char * line,int len&#41;
	&#123;
		char *nb = _buf;
		nb = nb + &#40; _ln * _w * _c &#41;;
		for&#40;int i=0;i<len;i++&#41;
		&#123;
			nb&#91;i&#93; = line&#91;i&#93;;
		&#125;
		_ln++;
	&#125;
	
	char *_buf;	 
	int _w,_h,_c,_ln;
&#125;;

And here's the texture constructor that invokes it,

Code: Select all

	Texture&#40;char *file,ImageFormat form&#41;
	&#123;
	
		_coordset=0;
		_filename = file;
		char *tex;
		switch&#40; form &#41;
		&#123;
			case JPEG&#58;
				JpgLoader *jl = new JpgLoader;
				Img * img = jl->LoadJpg&#40; &#40;const char *&#41; file &#41;;
				if&#40; img == NULL &#41;
				&#123;
					printf&#40;"Unable to load texture\n"&#41;;
					Logger->Log&#40;"Unable to load jpg %s \n",file&#41;;
					exit&#40;0&#41;;
				&#125;
				else
				&#123;
					Logger->Log&#40;"Loaded jpg %s \n",file &#41;;
				&#125;
				
				_w = img->_w;
				_h = img->_h;
				glGenTextures&#40;1, &_gltex&#41;;
		    glBindTexture&#40;GL_TEXTURE_2D, _gltex&#41;;   // 2d texture &#40;x and y size&#41;
				glTexParameteri&#40;GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR&#41;; 
		   	glTexParameteri&#40;GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR&#41;; 
				tex = &#40;char *&#41;malloc&#40;_w*_h*4&#41;;
					for&#40;int x=0;x<_w;x++&#41;
					&#123;
						for&#40;int y=0;y<_h;y++&#41;
						&#123;
							char *b = tex+&#40;y*_w*4&#41;+x*4;
							char *a = img->_buf+&#40; &#40;&#40;_h-1&#41;-y&#41;*_w*3&#41;+x*3;
							b&#91;0&#93; = a&#91;0&#93;;
							b&#91;1&#93; = a&#91;1&#93;;
							b&#91;2&#93; = a&#91;2&#93;;
							int targ = &#40;int&#41;b&#91;0&#93; + &#40;int&#41;b&#91;1&#93; + &#40;int&#41;b&#91;2&#93;;
							if&#40; targ>0 &#41;
							&#123;
								b&#91;3&#93; = 255;
							&#125;
							else
							&#123;
								b&#91;3&#93; = 0;
							&#125;
							b&#91;3&#93; = targ;
							
						&#125;
					&#125;			
					
					glTexImage2D&#40;GL_TEXTURE_2D, 0, 4, _w, _h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex&#41;;
					glBindTexture&#40;GL_TEXTURE_2D,0&#41;;
					_raw = tex;
				break;
			case BMP&#58;
				 Image *image1;
		     image1 = &#40;Image *&#41; malloc&#40;sizeof&#40;Image&#41;&#41;;
		    	if &#40;image1 == NULL&#41; &#123;
						printf&#40;"Error&#58;Unable to allocate memory for texture.\n"&#41;;
						exit&#40;0&#41;;
		    	&#125;
		      if &#40;!ImageLoad&#40;file, image1&#41;&#41; &#123;
						printf&#40;"Error&#58;Unable to load image.\n"&#41;;
						Logger->Log&#40;"Could not load texture %s \n",file&#41;;
						return;
					&#125;
					Logger->Log&#40;"Loaded texture.%s \n",file&#41;;
					_w = image1->sizeX;
					_h = image1->sizeY;
		    	glGenTextures&#40;1, &_gltex&#41;;
		    	glBindTexture&#40;GL_TEXTURE_2D, _gltex&#41;;   // 2d texture &#40;x and y size&#41;
				  glTexParameteri&#40;GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR&#41;; 
		   	  glTexParameteri&#40;GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR&#41;; 
					
					tex = &#40;char *&#41;malloc&#40;image1->sizeX*image1->sizeY*4&#41;;
					for&#40;int x=0;x<image1->sizeX;x++&#41;
					&#123;
						for&#40;int y=0;y<image1->sizeY;y++&#41;
						&#123;
							char *b = tex+&#40;y*image1->sizeX*4&#41;+x*4;
							char *a = image1->data+&#40;y*image1->sizeX*3&#41;+x*3;
							b&#91;0&#93; = a&#91;0&#93;;
							b&#91;1&#93; = a&#91;1&#93;;
							b&#91;2&#93; = a&#91;2&#93;;
							int targ = &#40;int&#41;b&#91;0&#93; + &#40;int&#41;b&#91;1&#93; + &#40;int&#41;b&#91;2&#93;;
							if&#40; targ>0 &#41;
							&#123;
								b&#91;3&#93; = 255;
							&#125;
							else
							&#123;
								b&#91;3&#93; = 0;
							&#125;
							b&#91;3&#93; = targ;
							
						&#125;
					&#125;			
					
		    	glTexImage2D&#40;GL_TEXTURE_2D, 0, 4, image1->sizeX, image1->sizeY, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex&#41;;
					glBindTexture&#40;GL_TEXTURE_2D,0&#41;;
					_raw = tex;
			break;
		&#125;
		
			
	&#125;
The wierd thing is though, it used to work, but now it flat out crashes everytime, even if it's just a lone call. So that would seem to point to memory getting trampled on as recless suggested.

I've had that a few times, app running ok, then not after introducing some new code that also uses malloced memory.

Ralph, did you ever convert memmgr to psp? I would like to use it, but I've never ported anything beside raptor, and I partly wrote that myself so it was a lot easier than some fancy memory debugger. :)
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

There's nothing to 'port' really, as it only uses stdc++ functions.
Thanks, for anyone else using that version, change the line:
#include <new>
to
#include <new.h>
Then comment out #include "stdafx" and add -fexceptions to the makefile.
This should let you compile Paul Nettles original memory manager with your C++ project. Maybe I'll take a look at your jpeg loader when I find time, but I'm pretty sure there's a error somewhere.
Believe me when I say libjpeg does not have any such errors ;)
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
Kojima
Posts: 275
Joined: Mon Jun 26, 2006 3:49 am

Post by Kojima »

Sounds easy enough. I'm sure I'll still manage to mess it up of course but can't blame anyone for that :)

As for jpeg, I believe ya, I'm just not used to these sorts of bugs. Too much time using C# and blitzmax for my own good :)
Post Reply