哈希表 - 分段错误

时间:2017-02-03 12:56:23

标签: c hashtable

不知道为什么我在这里遇到分段错误。我正在尝试创建一个会发生冲突的哈希表,数据应该是字符串。所以我正在为数据使用char数组。 需要在最后检测碰撞。

#define SIZE 20    
struct DataItem
{
    char data[50];
    int key;
};

struct DataItem* hashArray[SIZE];
struct DataItem* dummyItem;
struct DataItem* item;

int hashCode(int key)
{
    return key % SIZE;
}
void insert(int key, char data[50])
{

    struct DataItem *item = (struct DataItem*) malloc(sizeof(struct DataItem));
    strcpy(item->data, data);
    item->key = key;

//get the hash 
    int hashIndex = hashCode(key);

//move in array until an empty or deleted cell
    while (hashArray[hashIndex] != NULL && hashArray[hashIndex]->key != -1)
    {
        //go to next cell
        ++hashIndex;

        //wrap around the table
        hashIndex %= SIZE;
    }

    hashArray[hashIndex] = item;
}

struct DataItem* delete(struct DataItem* item)
{
    int key = item->key;

    //get the hash 
    int hashIndex = hashCode(key);

    //move in array until an empty
    while (hashArray[hashIndex] != NULL)
    {

        if (hashArray[hashIndex]->key == key)
        {
            struct DataItem* temp = hashArray[hashIndex];

            //assign a dummy item at deleted position
            hashArray[hashIndex] = dummyItem;
            return temp;
        }

        //go to next cell
        ++hashIndex;

        //wrap around the table
        hashIndex %= SIZE;
    }

    return NULL;
}

int detect_collisions()
{
    int i = 0;
    int collision = 0;
    for (i = 0; i < SIZE; i++)
    {
        if (hashArray[i] != NULL)
        {
            if (hashArray[i]->key == hashArray[i + 1]->key)
                ;
            collision++;
        }

    }
    return collision;
}

void display()
{
    int i = 0;

    for (i = 0; i < SIZE; i++)
    {
        if (hashArray[i] != NULL)
        {
            printf("Phli dafa: %d\n", i);
            printf(" (%d,%s)", hashArray[i]->key, hashArray[i]->data);
        }
        else
            printf(" ~~ ");
    }

    printf("\n");
}
int main()
{
    dummyItem = (struct DataItem*) malloc(sizeof(struct DataItem));
    strcpy(dummyItem->data, NULL);
    dummyItem->key = -1;

    insert(1, "check");
    display();
    delete(item);
}

3 个答案:

答案 0 :(得分:3)

你有问题:

strcpy(dummyItem->data,NULL);

因为strcpy将取消引用NULL指针。

要输入空字符串,请使用:

strcpy(dummyItem->data, "");

你的第二个问题是:

delete(item);
此时

item为NULL。所以这里:

struct DataItem* delete(struct DataItem* item)
{
    int key = item->key;
              ^^^^^^

取消引用NULL指针。

也许你的删除功能应该是:

struct DataItem* delete(int key)
{

第三个问题在这里(这里实际上有3个问题):

for (i = 0; i < SIZE; i++)
{
    if (hashArray[i] != NULL)
    {
        if (hashArray[i]->key == hashArray[i + 1]->key)
                                 ^^^^^^^^^^^^^^^^
                                 a) May be NULL
                                 b) Out of range when i == size-1
            ;
           ^^^
           c) Delete this
        collision++;
    }

}

我的猜测是你想要的:

for (i = 0; i < SIZE-1; i++)        // Notice
{
    if (hashArray[i] != NULL && hashArray[i + 1] != NULL)   // Notice
    {
        if (hashArray[i]->key == hashArray[i + 1]->key)
        {
            collision++;
        }
    }
}

答案 1 :(得分:2)

问题是

memset(dummyItem->data, 0x00, sizeof(dummyItem->data));

它会尝试将NULL指向的字符串(不是指向字符串..)复制到数组中。所以它调用了Undefined Behavior

你想要的(我猜)是

dummyItem->data[0] = 0x00;

dummyItem->data[0] = '\0';

malloc

另请注意,您必须始终检查NULL返回值:它可能无法返回dummyItem = malloc(sizeof(struct DataItem)); if ( dummyItem != NULL) { // YOUR STUFF }

if (hashArray[i]->key == hashArray[i + 1]->key)

你还有一个;

之后
delete(item);

将其删除。

我能看到的最后一件事

insert

是UB,因为item未初始化,因为struct DataItem *item = (struct DataItem*) malloc(sizeof(struct DataItem)); 函数中的代码使用局部变量,也许你想要更改

item = malloc(sizeof(struct DataItem));

if (hashArray[i]->key == hashArray[i + 1]->key)

编辑1

您还使用

访问数组越界
hashArray[i + 1]
i = SIZE-1

hashArray[i + 1]超出范围 此外,NULL可以是open ("fileA.txt", "r") as fileA: for line in fileA: print(line); 或未初始化。

答案 2 :(得分:0)

如果在打开调试的情况下编译代码(即使用gcc的-g选项),然后在调试器中运行它,它将告诉您seg故障发生在哪些行。我可以看到有两个地方导致了seg错误 - strcpy传递了NULL,并且调用了delete(item),其中item仍为NULL。大概是因为您认为您正在使用insert中定义的那个而不是全局定义的那个。