1819732 Members
3098 Online
109606 Solutions
New Discussion юеВ

Problem with c and qsort

 
SOLVED
Go to solution
Mary Rice
Frequent Advisor

Problem with c and qsort

Hello everyone,

I'm having a problem using the qsort library function to sort an array of up to 1000 records. I can print the array out but as soon as I call qsort(), I see "Bus error (coredump)". This looks very simple but it crashes everytime I run it. If I comment out the qsort() call everything works fine. I think something is wrong with my comparison routine but I'm not sure. Any help will be greatly appreciated.

Thank you, Mary
9 REPLIES 9
A. Clay Stephenson
Acclaimed Contributor
Solution

Re: Problem with c and qsort

Hi Mary:

You are right; it is very simple. I see several things I don't really like. You need to work on your type casting BUT your real problem is the element_size parameter, 90. Where in the Wide World or Sports did that come from? I kinda, sorta added up your struct's size and if I totally ignored field alignment then I could get 90. This is BAD!!!
replace your 90 with sizeof(struct DESC_STRUCT) and I think you will run. Moreover, sizeof() will cast size_t and that is what qsort expects.

Regards, Clay
If it ain't broke, I can fix that.
Mary Rice
Frequent Advisor

Re: Problem with c and qsort

Thanks Clay.

I just noticed that you had responded. That fixed my problem. I did just add up the fields in the struct and I thought that was what qsort expected as a size. I guess not. Following your advice, I replaced the 90 with a sizeof() and I no longer crash! I also added a printf("Record Size: %d\n",sizeof(struct DESC_STRUCT)) and it displayed '96'. That was my problem.

You said that you saw some other things that you didn't really like. At the risk of being hit with another one of your bricks, would you mind pointing those out to me as well? I've only been using C/C++ for a few months so any help you can give will be really appreciated.

Thank you again, Mary
A. Clay Stephenson
Acclaimed Contributor

Re: Problem with c and qsort

Hi Mary:

Because your program is so small, I'll download your attachment and edit it and repost it in a while. Lesson Number 1: Always use sizeof(); never hardcode struct/variable sizes in your code. At the very least, it will make your code non-portable. There are some compiler options, to force non-standard field alignments but it is far better to allow the compiler to choose the defaults. In most cases, fields start at word boundaries. This makes the code execute faster at the slight expense of wasted space.

Regards, Clay
If it ain't broke, I can fix that.
A. Clay Stephenson
Acclaimed Contributor

Re: Problem with c and qsort

Hi Mary:

I made all the changes in about three minutes so there wasn't that much really wrong. I did change the indentation to match my own style but that's just different; yours is certainly not wrong. I had to make up a fake load_array function since your code didn't have one. I assume the real thing loads from a file, pipe, or database.

1) I changed the include statements to bring in more appropriate header files; specifically those which have the prototypes for qsort & strcmp.

2) Note that I changed your declaration of your struct to a typedef AND now we have 'desc_struct' instead of 'struct DESC_STRUCT'; it's much easier to type but more importantly I separated the declaration of your array from the typedef of the struct.
Typically, data structures used by several files should be put in a header file (e.g. local.h) and #include'ed.

3) I changed your array size '1000' to a define. This means that any change in the future just requires that you change that one define.

4) Your compare_desc_structs function has very loose typing. Note that now, the formal parameters conform to the prototype that qsort expects but the pointers are explicitly cast as pointers to the needed type. This is considered a much cleaner coding style. Note also that I went through a few hoops to make sure that the function returns a completely valid int rather than a long. This is actually a bit of overkill but for teaching purposes, it's the really tight way to do it.

5) You main was declared int but you didn't return a result. Because the OS evaluates this return value, you should always make certain your main returns with a value or that you call exit() with a value.

6) Minor point but notice the (void) before the printf()'s and sprintf()'s. This is a way of saying yes, I know you return a value but I am explicitly ignoring it.

7) Note that most of the functions are now declared static (i.e. file scope). If a function does not need to be visible outside the file then use the static declaration.

The last point is the one that first caught my eye. Why the limit of 1000? I know - you'll never have that many. Famous last words. The best way to do this is with dynamic arrays. They are quite easy to implement and accomplish two things: 1) No limits 2) No wasted space because you declare huge static arrays that are almost always very sparsely populated. Once you create a set of dynamic array routines, you find that they will replace most of your static arrays and most linked lists as well.

P.S. Learn to use lint. It would have caught most of this stuff.

Hopefully, I've been a good boy and haven't clobbered you.

Regards, Clay
If it ain't broke, I can fix that.
Mary Rice
Frequent Advisor

Re: Problem with c and qsort

Thank you Clay. I will assign points later. I have been studying your comments about my code and I understand and agree with most of your ideas.

I now have another problem and I hope you or someone else can help me. The date in this application is stored as a 12 character string, "MMDDYYhhmmss'", MM = month, mm = minutes. I need qsort to sort this in reverse order so that the latest date appears first. The part that is really difficult is that years less than 80 should be 2000's and those greater than or equal to 80 should be 1900's.

Is there a way for qsort to do this?

Thank you, Mary
A. Clay Stephenson
Acclaimed Contributor

Re: Problem with c and qsort

Hi Mary,

The answer is yes it can but you will need to do a fair amount of work in your compare function. Getting qsort to reverse the order of the sort is simply a matter of reversing the sense of the compare operation. Normally, the comparison is diff = a - b but if we simply make the comparison diff = b - a, all is well.

The stupid 2-digit year stuff is more complicated but very doable. My psychic powers tell me that this application started off as a COBOL application. The best idea I can offer is to write a little routine that extracts part of your date string and converts it to an integer value. You would do this operation for the years, months, and days. I would extract the hhmmss and convert all to seconds so that only one comparison is needed.

I still have my last posting. I'll modify it. It shouldn't take more than a few minutes.

Clay

If it ain't broke, I can fix that.
Mary Rice
Frequent Advisor

Re: Problem with c and qsort

Hi Clay,

You are correct. This application did begin as a COBOL program but has been ported to Informix ESQL/C. I'm almost afraid to ask but how did you know?

Mary
A. Clay Stephenson
Acclaimed Contributor

Re: Problem with c and qsort

Okay Mary,

I think I have it. This is not the most efficient way to convert the dates because it is done each time the compare function is called. The better way, would be to add a some fields to your data structure and convert once as you load the data. The still better way would be to replace the string with a date field. Anyway, this should work.

Note that I actually left two compare functions in the code. Qsort now calls the reverse_compare.

Enjoy, Clay

If it ain't broke, I can fix that.
A. Clay Stephenson
Acclaimed Contributor

Re: Problem with c and qsort

Hi again Mary,

Well, as to how I knew this was once a COBOL program - For once, I better let discretion be the better part of valor and avoid phrases like 'state-of-the-art stupid' that tend to annoy people for some reason.

Regards, Clay

If it ain't broke, I can fix that.