【问题标题】:EXC_BAD_ACCESS using QSort on an Array of Chars within Structs in CEXC_BAD_ACCESS 在 C 中的结构中的字符数组上使用 QSort
【发布时间】:2017-04-07 08:39:48
【问题描述】:

我在这里搜索了许多答案,并在此基础上进行了一些更改,但在调用 qsort 函数时出现 EXC_BAD_ACCESS 错误。我的 IDE 指向我的 qsort 比较函数中的返回作为问题。我知道我正在为所有元素正确分配内存,因为如果我省略对 qsort 的调用,我可以毫无问题地打印字符串。有人能指出我正确的方向吗?

我的结构,看看我的导航深度:

typedef struct {
    unsigned int siteId;
    unsigned int tableTypeId;
    unsigned int surMatId;
    unsigned int strucMatId;
    char *streetAve;
    unsigned int neighbourhoodId;
    char *neighbourhoodName;
    unsigned int ward;
    char *latitude;
    char *longitude;
} Entries;

typedef struct {
    int size;
    Entries **entry;
} PicnicTable;

typedef struct {
    Table *tableTypeTable;
    Table *surfaceMaterialTable;
    Table *structuralMaterialTable;
    NeighbourHoodTable *neighborhoodTable;
    PicnicTable *picnicTableTable;
} DataBase;

extern DataBase *DB;




Entries **ent = DB->picnicTableTable->entry;
qsort(ent,DB->picnicTableTable->size-1, sizeof(Entries*), cmpfunc); typedef struct {
    unsigned int siteId;
    unsigned int tableTypeId;
    unsigned int surMatId;
    unsigned int strucMatId;
    char *streetAve;
    unsigned int neighbourhoodId;
    char *neighbourhoodName;
    unsigned int ward;
    char *latitude;
    char *longitude;
} Entries;

typedef struct {
    int size;
    Entries **entry;
} PicnicTable;

typedef struct {
    Table *tableTypeTable;
    Table *surfaceMaterialTable;
    Table *structuralMaterialTable;
    NeighbourHoodTable *neighborhoodTable;
    PicnicTable *picnicTableTable;
} DataBase;

extern DataBase *DB;

这是调用的样子:

Entries **ent = DB->picnicTableTable->entry;
qsort(ent,DB->picnicTableTable->size-1, sizeof(Entries*), cmpfunc);

比较函数是:

int cmpfunc(const void *a, const void *b) { 
    Entries *left = *(Entries**)a;
    Entries *right = *(Entries**)b;

    return strcmp(left->neighbourhoodName, right->neighbourhoodName);
}

picnicTableTable和Entry在这个malloc之后初始化:

DB->picnicTableTable = malloc(sizeof(PicnicTable));
DB->picnicTableTable->entry = malloc(numEntries*sizeof(Entries)+1);
DB->picnicTableTable->size = numEntries;

while ((c=fgetc(IN)) != EOF) {
        if (c == ',' && row > 0) {
            switch (column) {
                case 0: neighbourhoodName = copyToChar(buff, begin, i);
...
}

copyToChar 获取缓冲区的一部分并分配内存,然后返回一个指向我分配的值的指针:

char * copyToChar(const char * buff, int begin, int end) {
    char *temp = malloc(end - begin + 1);
    int j = 0;

    for (int i = begin; i < end; i++, j++)
        temp[j] = buff[i];
    temp[j] = '\0';

    return temp;
}

并且在我遍历文件中的每一行之后填充数组(这只是一个条目):

DB->picnicTableTable->entry[row]->neighbourhoodName = malloc(strlen(neighbourhoodName)*sizeof(char)+1);

a->neighbourhoodName 的值为 NULL,这让我很困惑。 qsort 不会将数组中的两个值传递给比较函数吗?

感谢您的宝贵时间!

【问题讨论】:

  • @Jean-FrançoisFabre qsort 将指针传递给它正在排序的数组中的元素,如果数组中的元素是指针,它将是指向指针的指针。
  • 好的,不是这样。我仍然认为Entries * 的 typedef 会使代码更清晰。
  • 在调试器中,捕捉到正在运行的崩溃,ab 的值是多少?它们看起来有效吗? (Entries **) a(Entries **) b 呢? neighbourhoodName 成员呢?
  • 另外,你如何初始化DB?你如何初始化DB-&gt;picnicTableTable?你如何初始化DB-&gt;picnicTableTable-&gt;entry?您可以尝试创建一个Minimal, Complete, and Verifiable Example 并展示给我们吗?

标签: c pointers struct exc-bad-access


【解决方案1】:

小心。您将 entry 声明为指向指针的指针(指向指针数组的第一个元素)

typedef struct {
    int size;
    Entries **entry;
} PicnicTable;

但是将它初始化为一个单纯的动态数组,即指向Entrys数组的第一个元素的指针:

DB->picnicTableTable->entry = malloc(numEntries*sizeof(Entries)+1);

如果你想要一个指针数组来加速 qsort,你应该单独构建它:

typedef struct {
    int size;
    Entries *entry;
    Entries **pentry;
} PicnicTable;

DB->picnicTableTable->entry = malloc(numEntries*sizeof(Entries)+1);
DB->picnicTableTable->pentry = malloc(numEntries*sizeof(&Entries)+1);
for (int i=0; i<=numEntries; i++) { // initialize the array of pointers
    pentry[i] = entry + i;
}

目前cmpfunc 的定义与您对DB-&gt;picnicTableTable-&gt;entry 的初始化不一致。

【讨论】:

  • 为什么不明确说这个分配:DB-&gt;picnicTableTable-&gt;entry = malloc(numEntries*sizeof(Entries)+1); 没有意义,是错的?
  • @alk:因为我的英语没有让我找到更好的词:-(。更严重的是,我真的认为说一个是结构数组,另一个是指向结构的指针数组已经足够了。我试图给 OP 一个提示,而不是仅仅说 那是错误的,他应该已经理解了,因为他的程序没有给出预期的结果。
  • 我的评论没有任何冒犯的意思,我更欣赏尊重的人。 :-)
  • 感谢@SergeBallesta 的提示,它们确实引导我朝着正确的方向前进。
猜你喜欢
  • 2019-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-02
相关资源
最近更新 更多