代码之家  ›  专栏  ›  技术社区  ›  user2261877

Malloc示例与qsort崩溃?

  •  2
  • user2261877  · 技术社区  · 11 年前

    嘿,我发现了一个将malloc与一组structs一起使用的例子,这些structs非常适合我想要做的事情,但当我将其与qsort组合时,我需要根据structs的“数字”值进行排序,我运气不太好。该代码符合要求,没有任何错误,但实际上并没有运行,只是崩溃了。由于我是一个初学者,我不知道是什么导致了这个问题。如果有人能阐明这一点,那就太棒了,谢谢!

    // 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;
    }
    
    1 回复  |  直到 11 年前
        1
  •  3
  •   A4L    11 年前

    您以错误的方式传递数组。

    应该是

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

    qsort 期望作为第一个参数的指针指向要排序的数据的起始位置,而这是 the_array 不是它的地址 &the_array 既然你已经这样声明了

    DATA    *the_array = NULL;
    

    输出将是:

    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!
    

    结果是 快速排序 认为数组从的地址开始 阵列(_a) 并开始访问不允许访问的其他存储器区域。

    编辑

    我已经尝试了4000个单词,但无法使其崩溃,以下是我如何修改代码以从文件中读取的( strdup 相当于 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;               
    }
    

    执行方式如下:

    out.exe < lorem.txt
    

    数据已正确排序、打印和释放