Domanda

Hey I found an example of using malloc with an array of structs that fits what I'm trying to do quite well, but when I go to combine it with qsort which I need to sort by the "number" value of struct I'm not having much luck. The code complies fine with no errors but doesn't actually run and just crashes. Since I'm a beginner I have no idea what's causing the problem. If someone could shed some light on this that be brilliant thanks!

// Example code from "a tutorial on 'dynamic' arrays in C"
// http://fydo.net

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct DATA{
    char *name;
    int number;
} DATA;

DATA    *the_array = NULL;
int     num_elements = 0; // To keep track of the number of elements used
int     num_allocated = 0; // This is essentially how large the array is
int  compare(struct DATA *, struct DATA *);
typedef int (*compfn)(const void*, const void*);

int compare(struct DATA *elem1, struct DATA *elem2)
{
   if ( elem1->number < elem2->number)
      return -1;

   else if (elem1->number > elem2->number)
      return 1;

   else
      return 0;
}



int AddToArray (DATA item)
{
    if(num_elements == num_allocated) { // Are more refs required?

        // Feel free to change the initial number of refs and the rate at which refs are allocated.
        if (num_allocated == 0)
            num_allocated = 3; // Start off with 3 refs
        else
            num_allocated *= 2; // Double the number of refs allocated

        // Make the reallocation transactional by using a temporary variable first
        void *_tmp = realloc(the_array, (num_allocated * sizeof(DATA)));

        // If the reallocation didn't go so well, inform the user and bail out
        if (!_tmp)
        {
            fprintf(stderr, "ERROR: Couldn't realloc memory!\n");
            return(-1);
        }

        // Things are looking good so far, so let's set the
        the_array = (DATA*)_tmp;
    }

    the_array[num_elements] = item;
    num_elements++;

    return num_elements;
}

int main()
{
    // Some data that we can play with
    char *names[6] = { "Steve", "Bill", "George", "fydo", "Dave", "Jim" };
    int numbers[6] = { 42, 33, 15, 74, 5, 20 };
    int i;

    // Populate!
    for (i = 0; i < 6; i++)
    {
        DATA temp;

        temp.name = malloc((strlen(names[i]) + 1) * sizeof(char));
        strncpy(temp.name, names[i], strlen(names[i]) + 1);
        temp.number = numbers[i];

        if (AddToArray(temp) == -1) // If there was a problem adding to the array,
            return 1;               // we'll want to bail out of the program. You
                                    // can handle it however you wish.
    }

    //sort by number:
    qsort((void *) &the_array, 6, sizeof(struct DATA), (compfn)compare );

    // Regurgitate!
    for (i = 0; i < 6; i++)
    {
        printf("%s's number is %d!\n", the_array[i].name, the_array[i].number);
    }

    // Deallocate!
    for (i = 0; i < 6; i++)
    {
        free(the_array[i].name);
    }

    free(the_array);

    // All done.
    return 0;
}
È stato utile?

Soluzione

You are passing the array in the wrong way.

it should be

qsort(the_array, 6, sizeof(struct DATA), (compfn)compare );

qsort expects as first argument a pointer to where the data to be sorted starts, and this is the_array not its address &the_array since you have declared it this way

DATA    *the_array = NULL;

The output would be:

Dave's number is 5!
George's number is 15!
Jim's number is 20!
Bill's number is 33!
Steve's number is 42!
fydo's number is 74!

What happens is that qsort thinks the array is starting at the address of the_array and start accessing other memory areas where it is not allowed to.

EDIT

I have tryed it with 4000 words and can't get it to crash, here is how i modified the code to read from a file, (strdup is ust handy equivalent to malloc + strcpy)

char name[100];
while(1 == scanf("%s", name)) {
    DATA temp;
    temp.name = strdup(name);
    temp.number = rand();
    if (AddToArray(temp) == -1) 
        return 1;               
}

executed like this:

out.exe < lorem.txt

The data is correctly sorted, printed and free-ed

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top