delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2000/01/20/14:39:37

From: "Kenneth F. Henderson Jr." <KenH AT Hughes DOT Net>
Newsgroups: comp.os.msdos.djgpp
Subject: qsort() bug? Or invalid usage???
Lines: 102
Message-ID: <R0Gh4.2371$Ll5.3502@news2.randori.com>
Date: Thu, 20 Jan 2000 15:41:37 GMT
NNTP-Posting-Host: 206.97.42.111
X-Trace: news2.randori.com 948382897 206.97.42.111 (Thu, 20 Jan 2000 07:41:37 PST)
NNTP-Posting-Date: Thu, 20 Jan 2000 07:41:37 PST
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

 I think I may have found a bug in qsort().  I'm porting the Descent 2 (a game)
source code to DJGPP, and qsort is passing the address of element -1 to the
sort function occationally when the list of objects to render is sorted.  It
looks to be either a bug in qsort() or the D2 programmers providing an
illegal(???) sort_func (it depends on which 2 specific elements are compared as
to what the function returns... is this legal?  If not, any advice on what to
do about it?).  I think this construct is legal (although it's not surefire to
produce the desired sort order, but that isn't absolutely critical - being fast
and not clobbering memory is) - at the very least, can it be made to not try to
compare/sort non-existant elements...?
 Please email a copy of replies directly to kenh AT hughes DOT net.

 I'm using the following packages (info from the relevant .ver files):
djdev201 Development Kit and Runtime
gcc281b.zip GNU C compiler version 2.8.1, binaries and documentation
bnu281b GNU binutils 2.8.1 for DJGPP V2   (binaries and docs)

 Here's a code sample that produces the bug (compile with "gcc qsortbug.c"):
//Start qsortbug.c
#include <stdio.h>

//Data given to qsort
typedef struct
{
	int	objnum;
	int	dist;	//fixed-point 16:16
} sort_item;

sort_item	sort_list[] =
{/*0*/{31,647424},/*1*/{29,869248},/*2*/{28,1010176},/*3*/{27,1185984},/*4*/{26,1327808},/*5*/{25,2518400},/*6*/{0,0},/*7*/{30,756352}};
int		n_sort_items = sizeof(sort_list)/sizeof(*sort_list);

//Data used by sort_func
#define	OBJ_FIREBALL		1
#define	OBJ_WEAPON		5
#define	VCLIP_AFTERBURNER_BLOB	95

typedef struct
{
	unsigned char	type;
	unsigned char	id;
	int		size;	//fixed-point 16:16
} object;

object Objects[] =
{/*0*/{4,0,310325},/*1*/{1,88,196608},/*2*/{1,88,196608},/*3*/{1,88,196608},/*4*/{1,12,131072},/*5*/{1,88,196608},/*6*/{1,88,196608},/*7*/{1,88,196608},/*8*/{5,31,11883},/*9*/{5,31,11883},/*10*/{9,3,748295},/*11*/{5,6,65536},/*12*/{2,30,736493},/*13*/{1,2,276184},/*14*/{1,2,276184},/*15*/{1,2,276184},/*16*/{1,2,276184},/*17*/{5,31,11883},/*18*/{5,31,11883},/*19*/{7,42,262144},/*20*/{5,6,65536},/*21*/{5,48,85196},/*22*/{5,31,11883},/*23*/{5,31,11883},/*24*/{5,31,11883},/*25*/{5,6,65536},/*26*/{1,88,196608},/*27*/{1,88,196608},/*28*/{1,88,196608},/*29*/{1,88,196608},/*30*/{1,5,458752},/*31*/{1,88,196608},/*32*/{5,6,65536},/*33*/{5,6,65536},/*34*/{5,6,65536},/*35*/{2,30,736493}};

//The comparison function
int sort_func(const sort_item *a,const sort_item *b)
{
	int	delta_dist;
	object	*obj_a,*obj_b;

//Debugging code
	printf("Comparing %d%s and %d%s.\n",
((int)a-(int)sort_list)/(int)sizeof(*sort_list),
( (a<(&(sort_list[0]))) || (a>=(&(sort_list[n_sort_items]))) )?" (BUG)":"",
((int)b-(int)sort_list)/(int)sizeof(*sort_list),
( (b<(&(sort_list[0]))) || (b>=(&(sort_list[n_sort_items]))) )?" (BUG)":""
	);

	if(	(a<(&(sort_list[0		])))	||
		(b<(&(sort_list[0		])))	||
		(a>=(&(sort_list[n_sort_items	])))	||
		(b>=(&(sort_list[n_sort_items	])))	)
	{	//We have hit the bug.
		//Return 0 in the hopes that qsort won't trash memory,
		// and also so we don't try to look at objects that aren't there
		return 0;
	}

//Actual comparision code
	delta_dist= a->dist - b->dist;

	obj_a = &Objects[a->objnum];
	obj_b = &Objects[b->objnum];

	if (abs(delta_dist) < (obj_a->size + obj_b->size)) {
		if (obj_a->type == OBJ_WEAPON || (obj_a->type == OBJ_FIREBALL && obj_a->id != VCLIP_AFTERBURNER_BLOB))
		{
			if (!(obj_b->type == OBJ_WEAPON || obj_b->type == OBJ_FIREBALL))
				return -1;
			else;
		}
		else
			if (obj_b->type == OBJ_WEAPON || (obj_b->type == OBJ_FIREBALL && obj_b->id != VCLIP_AFTERBURNER_BLOB))
				return 1;
	}

	return delta_dist;
//
}

main()
{
	printf("n_sort_items = %d\n",n_sort_items);
	qsort(sort_list,n_sort_items,sizeof(*sort_list),(void *)sort_func);
}
//End qsortbug.c

 Thanks in advance for any help/fixes

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019