Invalid Type Combination In Ordering Comparison.


Alvin

Member
Joined
Mar 26, 2006
Messages
171
Alright, I'm making a simple game which has blocks which are either on or off (like lights). Details aren't important, but I have a grid of these blocks. Anyway, everything compiles nice and fine, and my code appears to be fairly clean. I'm testing what I've thrown together, but the game segfaults as soon as it tries SDL_Flip().

Let me elaborate.

I have a pointer array of block classes in my game class (main class). Each block has it's own SDL_Surface * entity, and so on (see below for source). Each pointer is initialised in the game class with the block constructor. Every surface in the grid is filled in as "off", so none of them are NULL. In the main loop of my game class, I call the flip function I have (which calls SDL_Flip(screen)). This is where is goes wrong. It segfaults at this point, and GDB reports this:

Code:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1212929824 (LWP 16397)]
Error while running hook_stop:
Invalid type combination in ordering comparison.
0xb7ebdd5d in SDL_Flip () from /usr/lib/libSDL-1.2.so.0

I've never had this kind of error before, and asking on IRC/a few friends and Googling didn't reveal any solutions (in fact, Google returned very few distinct errors, and no SDL-specific ones).

Compiling with g++ ./lgt.cpp ./block.cpp ./game.cpp -o ./lgt -lSDL -Wall -ggdb on Linux.

Source (note - the game is called lgt (light game thing))
Tarball
Pasted source (quite a mouthfull):

lgt.h
Code:
#ifndef __LGT_H
#define __LGT_H

#include <SDL/SDL.h>

/* dimensions */
#define w 5
#define h 5
#define blockh 25
#define blockw 25
#define padding 5
#define screenw ((w * blockw) + ((w + 1) * padding))
#define screenh ((h * blockh) + ((h + 1) * padding))

/* screen settings */
#define screentype SDL_HWSURFACE|SDL_DOUBLEBUF
#define bpp 32

/* selected block RGB values */
#define selcolr 0xFF
#define selcolg 0x00
#define selcolb 0x00

/* unselected block RGB values */
#define offcolr 0xCC
#define offcolg 0xCC
#define offcolb 0xCC

/* background RGB values */
#define bgcolr 0xFF
#define bgcolg 0xFF
#define bgcolb 0xFF

/* block class */
class block
{
	private:
		SDL_Surface *screen;
		SDL_Surface *surface;
		Uint32 selcol;
		Uint32 offcol;
		bool on;
	
	public:
		block(SDL_Surface *);
		bool blit(int, int);
		void enabled(bool);
};

/* game class */
class game
{
	private:
		SDL_Surface *screen;
		Uint32 bgcol;
		block *grid[w][h];
		bool blitblock(int, int);
		bool flip();
	
	public:
		game();
		void mainloop();
};

#endif /* __LGT_H */

lgt.cpp
Code:
#include "lgt.h"

int main()
{
	game lgt = game();
	lgt.mainloop();
	
	return 0;
}

block.cpp
Code:
#include "lgt.h"

block::block(SDL_Surface *mscreen)
{
	screen = mscreen;
	surface = SDL_CreateRGBSurface(screentype, blockw, blockh, bpp,
			screen->format->Rmask, screen->format->Gmask, screen->format->Bmask,
			screen->format->Amask);
	
	if(!surface) {
		printf("couldn't create block sufrace: %s\n", SDL_GetError());
		exit(1);
	}
	
	selcol = SDL_MapRGB(screen->format, selcolr, selcolg, selcolb);
	offcol = SDL_MapRGB(screen->format, offcolr, offcolg, offcolb);
	
	/* default is off */
	on = false;
	
	if(SDL_FillRect(surface, NULL, offcol) == -1) {
		printf("couldn't fill block rect: %s\n", SDL_GetError());
		exit(1);
	}
}

bool block::blit(int x, int y)
{
	/* whole surface should be copied to (x, y) on screen */
	SDL_Rect *dst;
	memset(dst, 0, sizeof(dst));
	dst->x = x;
	dst->y = y;
	
	/* blit the whole surface based on dst */
	if(!SDL_BlitSurface(surface, NULL, screen, dst))
		return true;
	else
		return false;
}

void block::enabled(bool active)
{
	on = active;
	
	/* if it's on, fill it with the enabled colour */
	if(on)
		SDL_FillRect(surface, NULL, selcol);
	/* if it's off, fill it with the disabled colour */
	else
		SDL_FillRect(surface, NULL, offcol);
}

game.cpp
Code:
#include "lgt.h"

game::game()
{
	if(SDL_Init(SDL_INIT_VIDEO) < 0) {
		printf("couldn't initialise SDL: %s\n", SDL_GetError());
		exit(1);
	}
	
	screen = SDL_SetVideoMode(screenw, screenh, bpp, screentype);
	if(!screen) {
		printf("couldn't set video mode: %s\n", SDL_GetError());
		exit(1);
	}
	
	for(int i = 0; i < w; i++) {
		for(int j = 0; j < h; j++) {
			grid[i][j] = new block(screen);
		}
	}
}

bool game::blitblock(int x, int y)
{
	int bx = ((x * blockw) + ((x + 1) * padding));
	int by = ((y * blockh) + ((y + 1) * padding));
	
	return grid[x][y]->blit(bx, by);
}

bool game::flip()
{
	if(!SDL_Flip(screen))
		return true;
	else
		return false;
}

void game::mainloop()
{
	for(int i = 0; i < w; i++)
		for(int j = 0; j < h; j++)
			blitblock(i, j);
	
	flip();
	
	SDL_Delay(1000);
}

Thanks!
 
I was trying to debug this a bit, but when I put "fprintf(stderr, "x\n");" at the start of game::mainloop(), it suddenly started working. Dunno what that's about.
Anyway you shouldn't make #defines for stuff like 'w' and 'h' as the precompiler just replaces these. I changed them to stuff like WIDTH and HEIGHT etc, don't know if that made a difference...
 
Dr_Ian posted on Dec 3 2006 at 10:54 AM said:
I was trying to debug this a bit, but when I put "fprintf(stderr, "x\n");" at the start of game::mainloop(), it suddenly started working. Dunno what that's about.
Anyway you shouldn't make #defines for stuff like 'w' and 'h' as the precompiler just replaces these. I changed them to stuff like WIDTH and HEIGHT etc, don't know if that made a difference...
Wow, I don't know how you managed to figure that out, but it works. I've used fflush(stdout); instead, since I don't want garbage output, and it seems to work fine.

Thanks :)
 
Last edited by a moderator:
I wouldn't have any hope that your code will continue to work just by adding a fflush. If adding something like that fixes things then it usually suggests you've got a memory corruption problem somewhere, and it will certainly pop it's head up again very soon.

Just had a quick look through the code and I don't like the look of this -
Code:
	SDL_Rect *dst;
	memset(dst, 0, sizeof(dst));
	dst->x = x;
	dst->y = y;
You're creating a pointer to an SDL_Rect, then clearing the memory without allocating it first (which means you're probably overwriting some random bit of memory). There's no need to be using a pointer there. Use this instead -
Code:
   SDL_Rect dst;
	dst.x = x;
	dst.y = y;

	/* blit the whole surface based on dst */
	if(!SDL_BlitSurface(surface, NULL, screen, &dst))
 
I agree with woogal. But if you insisted on allocating memory, then: -
Code:
	memset(dst, 0, sizeof(dst));
even after allocation would be wrong. I think you would want to clear memory for the whole size of the structure (not the pointer to the structure).

e.g.

Code:
	memset(dst, 0, sizeof(*dst));
or

Code:
	memset(dst, 0, sizeof(SDL_Rect));
 
Back
Top