A
arne.muller
Hello,
I just had to find out that a program that runs fine under linux and
True64 alpha crashed with a segmentation fault under SunOS 5.8. I
drilled down and it appears that if the sun qsort gets a vector in
which all elements are equivalent, my comparsion function raises
SEGSEGV.
The problem seems to be that all elements are the same sun qsort
always passes NULL as the first element to the comparsion function. Is
this standard conform ? Well, I guess I miss something, so here comes
a test:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int n ;
double score;
} DS;
static int cmp(const void *aptr, const void *bptr);
int cmp(const void *aptr, const void *bptr) {
DS *a = *((DS**)aptr);
DS *b = *((DS**)bptr);
return a->score > b->score ? a->score == b->score ? 0 : -1 : 1;
}
int main(int argc, char *argv[]) {
DS** vec;
int i;
int n;
double f;
f = 1.0/(double)RAND_MAX;
n = argc > 0 ? atoi(argv[1]) : 5;
vec = (DS**)malloc(n * sizeof(DS*));
for ( i=0; i<n; i++ ) {
vec = (DS*)malloc(sizeof(DS));
if ( argv[2][0] == 'a' ) {
vec->score = rand()*f;
} else if ( argv[2][0] == 'b' ) {
vec->score = 3.123;
} else if ( argv[2][0] == 'c' ) {
vec->score = 3.123;
}
fprintf(stderr, "score = %f\n", vec->score);
}
if ( argv[2][0] == 'c' ) vec[0]->score = 445.6;
qsort(vec, n, sizeof(DS*), cmp);
fputs("*** sorted *** \n", stderr);
for ( i=0; i<n; i++ ) {
fprintf(stderr, "score = %f\n", vec->score);
}
return 0;
}
Then:
cc -g -o testit testit.c
running this on sunOS 5.8 gives:
3 random values are sorted
$$ ./testit 3 a
score = 0.513871
score = 0.175726
score = 0.308634
*** sorted ***
score = 0.513871
score = 0.308634
score = 0.175726
3 values (all the same) are sorted
$$ ./testit 3 b
score = 3.123000
score = 3.123000
score = 3.123000
Segmentation Fault
3 values (all but but) are the same
$$ ./testit 3 c
score = 3.123000
score = 3.123000
score = 3.123000
*** sorted ***
score = 445.600000
score = 3.123000
score = 3.123000
in gdb I found out that:
score = 3.123000
score = 3.123000
score = 3.123000
Program received signal SIGSEGV, Segmentation fault.
0x0001091c in cmp (aptr=0x2111c, bptr=0x21124) at testit.c:15
15 return a->score > b->score ? a->score == b->score ? 0 : -1 :
1;
(gdb) print a
$1 = (DS *) 0x0
(gdb) print b
$2 = (DS *) 0x21150
(gdb)
so the pointer passed to the cmp function are not NULL, but 'a' is NULL
(i.g. the de-referenced aptr). In my situtqtion I have a list of
structure to be sorted on the 'score' attribute, so I realy need a
pointer to DS structrue, and it happenes that sometimes there are only
a few elements in the array and they have the same score.
I realy got stuck here, any ideas wha's going on, and why other systems
(win32 with gcc, linux with gcc, True64 with cc) are more forgiving?
thanks for your help
+kind regards,
Arne
ps: I read http://c-faq.com/lib/qsort2.html (comp.lang.c FAQ list ·
Question 13.9) but still seem to miss the point ...
I just had to find out that a program that runs fine under linux and
True64 alpha crashed with a segmentation fault under SunOS 5.8. I
drilled down and it appears that if the sun qsort gets a vector in
which all elements are equivalent, my comparsion function raises
SEGSEGV.
The problem seems to be that all elements are the same sun qsort
always passes NULL as the first element to the comparsion function. Is
this standard conform ? Well, I guess I miss something, so here comes
a test:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int n ;
double score;
} DS;
static int cmp(const void *aptr, const void *bptr);
int cmp(const void *aptr, const void *bptr) {
DS *a = *((DS**)aptr);
DS *b = *((DS**)bptr);
return a->score > b->score ? a->score == b->score ? 0 : -1 : 1;
}
int main(int argc, char *argv[]) {
DS** vec;
int i;
int n;
double f;
f = 1.0/(double)RAND_MAX;
n = argc > 0 ? atoi(argv[1]) : 5;
vec = (DS**)malloc(n * sizeof(DS*));
for ( i=0; i<n; i++ ) {
vec = (DS*)malloc(sizeof(DS));
if ( argv[2][0] == 'a' ) {
vec->score = rand()*f;
} else if ( argv[2][0] == 'b' ) {
vec->score = 3.123;
} else if ( argv[2][0] == 'c' ) {
vec->score = 3.123;
}
fprintf(stderr, "score = %f\n", vec->score);
}
if ( argv[2][0] == 'c' ) vec[0]->score = 445.6;
qsort(vec, n, sizeof(DS*), cmp);
fputs("*** sorted *** \n", stderr);
for ( i=0; i<n; i++ ) {
fprintf(stderr, "score = %f\n", vec->score);
}
return 0;
}
Then:
cc -g -o testit testit.c
running this on sunOS 5.8 gives:
3 random values are sorted
$$ ./testit 3 a
score = 0.513871
score = 0.175726
score = 0.308634
*** sorted ***
score = 0.513871
score = 0.308634
score = 0.175726
3 values (all the same) are sorted
$$ ./testit 3 b
score = 3.123000
score = 3.123000
score = 3.123000
Segmentation Fault
3 values (all but but) are the same
$$ ./testit 3 c
score = 3.123000
score = 3.123000
score = 3.123000
*** sorted ***
score = 445.600000
score = 3.123000
score = 3.123000
in gdb I found out that:
score = 3.123000
score = 3.123000
score = 3.123000
Program received signal SIGSEGV, Segmentation fault.
0x0001091c in cmp (aptr=0x2111c, bptr=0x21124) at testit.c:15
15 return a->score > b->score ? a->score == b->score ? 0 : -1 :
1;
(gdb) print a
$1 = (DS *) 0x0
(gdb) print b
$2 = (DS *) 0x21150
(gdb)
so the pointer passed to the cmp function are not NULL, but 'a' is NULL
(i.g. the de-referenced aptr). In my situtqtion I have a list of
structure to be sorted on the 'score' attribute, so I realy need a
pointer to DS structrue, and it happenes that sometimes there are only
a few elements in the array and they have the same score.
I realy got stuck here, any ideas wha's going on, and why other systems
(win32 with gcc, linux with gcc, True64 with cc) are more forgiving?
thanks for your help
+kind regards,
Arne
ps: I read http://c-faq.com/lib/qsort2.html (comp.lang.c FAQ list ·
Question 13.9) but still seem to miss the point ...