【问题标题】:C segmentation fault 11 when implementing hashtable实现哈希表时的 C 分段错误 11
【发布时间】:2018-05-09 13:39:55
【问题描述】:

做一个关系数据结构项目,我将事物组织成一个哈希表。到目前为止,我已经做了一个插入和查找方法并且没有错误。当我尝试运行代码时,我得到了这个:

“插入 CSG touples” “分段错误 11”

我认为我没有正确分配某些东西,但我不知道是什么,考虑到它在说“插入 CSG touples”,我认为这在我的 createHashTable 函数中不是问题。这是我的代码

头文件:CSG.h

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

typedef struct CSG{
    char* Course;
    char* StudentId;
    char* Grade;
    struct CSG *next;

}CSG;

typedef struct CSGHASH{

    int size;
    CSG** table;

}CSGHASH;

CSGHASH* createHashTable(int size);

int hash(int CN);

CSG* makeCSG(char* Course, char* StudentId, char* Grade);

void printCSG(CSG guy);

//void printCSGLIST(CSGLIST guy);

int toInt(char* x);

CSG* lookup(CSGHASH *hashtable, char* course, char* StudentId, char* grade);

int insert(CSG* newGuy, CSGHASH* hashtable);

CSG.c

CSGHASH* createHashTable(int size){

    CSGHASH* hashtable = NULL;

    if(size<1)
        return NULL; // table cant be less than length of 1

    if((hashtable = malloc(sizeof(CSGHASH*)))== NULL)
        return NULL;

    if((hashtable->table = malloc(sizeof(CSG*) * size)) == NULL)
        return NULL;

    for(int i = 0; i<size; i++){

        hashtable->table[i] = malloc(sizeof(CSG));
        hashtable->table[i] = NULL;
        //hashtable->table[i]->next = NULL;
    }

    hashtable->size = size;

    return hashtable;
}

int hash(int CN){

    return CN%6;
}

CSG* makeCSG(char* Course, char* StudentId, char* Grade){

    //struct CSG tempCSG = malloc(sizeof(CSG));
    CSG* tempCSG = malloc(sizeof(CSG*));
    strcpy(tempCSG->Course, Course);
    strcpy(tempCSG->StudentId, StudentId);
    strcpy(tempCSG->Grade, Grade);
    return tempCSG;
}

void printCSG(CSG guy){

    printf("course: %s\n", guy.Course);
    printf("StudentId: %s\n", guy.StudentId);
    printf("Grade: %s\n", guy.Grade);
}

// void printCSGLIST(CSGLIST guy){


// }

int toInt(char* x){

    int count = 0;
    for(int i = 0; i< strlen(x); i++)
        count += (int) i;
    return count;
}


CSG* lookup(CSGHASH *hashtable, char* course, char* StudentId, char* grade){

    CSG* list;
    unsigned int hashNum = hash(toInt(course));

    for(list = hashtable->table[hashNum]; list!= NULL; list = list->next){

        if(strcmp(StudentId, list->StudentId) == 0){

            printf("Course: %s\n", list->Course);
            printf("Student ID: %s\n", list->StudentId);
            printf("Grade: %s\n", list->Grade);
            return list;
        }
    }
    printf("doesn't exist\n");
    return NULL;
}

int insert(CSG* newGuy, CSGHASH* hashtable){

    CSG* list;
    CSG* currList;
    unsigned int hashNum = hash(toInt(newGuy->Course));

    list = malloc(sizeof(CSG));

    currList = lookup(hashtable, newGuy-> Course, newGuy-> StudentId, newGuy-> Grade);

    if(currList != NULL){

        printf("already exists\n");
        return 2;
    }

    list->Grade = strdup(newGuy->Grade);
    list->StudentId = strdup(newGuy->StudentId);
    list->Course = strdup(newGuy->Course);
    list->next = hashtable->table[hashNum];
    hashtable->table[hashNum] = list;

    printf("CSG inserted\n");
    return 0;
}

主文件

/*
main4.c
*/

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

int main(int argc, char *argv[]){

CSGHASH *testHash = createHashTable(47);


printf("inserting CSG tuples \n");

CSG* tuple1 = makeCSG("CSC101", "12345", "A+");
CSG* tuple2 = makeCSG("CSC101", "67890", "B");
CSG* tuple3 = makeCSG("EE200", "67890", "B+");
CSG* tuple4 = makeCSG("EE200", "45213", "D");
CSG* tuple5 = makeCSG("CSC173", "98765", "C");
CSG* tuple6 = makeCSG("MTH142", "47474", "A");

insert(tuple1, testHash);
lookup(testHash, "CSC101", "12345", "*");

//printCSGLIST(lookup(tester, "CSC101", "12345", "*"));
}

如果有人能找出我做错了什么,我将不胜感激(抱歉,我知道有很多事情需要追查)。

更新

经过一点调试,问题似乎出在 makeCSG 函数中。希望这能让追踪更容易一点

【问题讨论】:

  • 使用 gdb 找出问题所在。
  • malloc(sizeof(CSGHASH*)) 只是为指针而不是结构分配空间。稍后malloc(sizeof(CSG*)) 也一样。
  • 在此之前仍然遇到分段错误。也很抱歉我对c很陌生,不知道如何使用gdb。做了一些研究,它看起来还没有安装在我的电脑上。
  • CSG* tempCSG = malloc(sizeof(CSG*));-->> `CSG* tempCSG = malloc(*tempCSG);`会做。
  • 你没有初始化结构内的指针。

标签: c segmentation-fault hashtable


【解决方案1】:

出现了快速传球:

 if((hashtable = malloc(sizeof(CSGHASH*)))== NULL)

错误,这将为指向 CSGHASH 的指针而不是 CSGHASH 本身分配足够的存储空间。认为您想摆脱星号。下面的 malloc() 也将遭受同样的命运。

【讨论】:

  • 以前有过这个。删除它,但我仍然遇到分段错误
【解决方案2】:

来自 CSG.h:

typedef struct CSG{
    char* Course;
    char* StudentId;
    char* Grade;
    struct CSG *next;

}CSG;

makeCSG() 你正在做:

CSG* makeCSG(char* Course, char* StudentId, char* Grade){

    //struct CSG tempCSG = malloc(sizeof(CSG));
    CSG* tempCSG = malloc(sizeof(CSG*));
    strcpy(tempCSG->Course, Course);
    strcpy(tempCSG->StudentId, StudentId);
    strcpy(tempCSG->Grade, Grade);
    return tempCSG;
}

makeCSG() 有几个问题:

第一个问题:

CSG* tempCSG = malloc(sizeof(CSG*));

这里,tempCSG 是一个指向CSG 的指针。所以你应该:

CSG* tempCSG = malloc(sizeof(CSG));

createHashTable() 中的类似问题:

if((hashtable = malloc(sizeof(CSGHASH*)))== NULL)

这应该是:

if((hashtable = malloc(sizeof(CSGHASH)))== NULL)

第二个问题:

strcpy(tempCSG->Course, Course);
strcpy(tempCSG->StudentId, StudentId);
strcpy(tempCSG->Grade, Grade);

这里,CourseStudentIdGrade 的类型为 char *,您正试图将一些值复制到您未分配内存的指针。在使用它们之前分配内存。

所以首先你应该这样做:

CSG* tempCSG = malloc(sizeof(CSG));
tempCSG->Course = malloc(100);
tempCSG->StudentId = malloc(20);
tempCSG->Grade = malloc(10);

然后

strcpy(tempCSG->Course, Course);
strcpy(tempCSG->StudentId, StudentId);
strcpy(tempCSG->Grade, Grade);
tempCSG->next = NULL;

另外,请确保在每次 malloc 调用后检查 malloc 返回。

【讨论】:

    【解决方案3】:

    基本上所有涉及char* 的东西都是错误的。您没有分配将数据复制到这些缓冲区所需的内存,实际上您根本没有初始化它们。

    您的代码有什么问题的简化版本:

    char* Course;
    strcpy(Course, "CSC101");
    

    这是导致致命错误的原因,因为我们从未分配过Course

    对于结构中的每个char*,您必须malloc() 有足够的空间来容纳数据,或者将它们声明为数组,因此当您为它们所在的结构保留内存时,它们已经被分配in,但会在编译时确定一个固定的大小。

    例子:

    typedef struct CSG
    {
        char Course[16];
        char StudentId[16];
        char Grade[16];
        struct CSG *next;
    } CSG;
    

    这确实是解决问题的最简单方法,如果您希望创建某种基本数据库,可以轻松地在文件上存储和恢复此结构,并保持代码更简洁,避免大量内存管理malloc()free() 到处都是。

    【讨论】:

      猜你喜欢
      • 2022-07-21
      • 1970-01-01
      • 2014-03-28
      • 2016-03-03
      • 2013-12-25
      • 2012-04-23
      • 2016-08-13
      • 2012-04-15
      相关资源
      最近更新 更多