C 中的 Abort Trap 6 错误和调试

Abort Trap 6 error in C and debugging

大家好,我已经完成了我的代码,当我尝试 运行 时,我收到了 "abort trap 6" 错误。我不知道这个错误是什么,也不知道如何找出我的代码在哪里出错。 c 相对较新,所以感谢您和我一起玩。这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define HASH_MULTIPLIER 65599
int htsize;

struct NodeType {
    char *str;
    int count;
    struct NodeType *next;
};
typedef struct NodeType Node;

/*Function prototypes*/
char *lowercase(char *str);
Node **ht_create(void);
unsigned int hash(const char *str);
int ht_insert(Node **Table, char *word);
void ht_print(Node **Table);
void ht_destroy(Node **Table);


int main(int argc, char *argv[])
{
    int n = 0;                                                      // current number of strings
    char *line = NULL;                                              // line buffer argument to getline()
    size_t length = 0;                                              // buffer size argument to getline()
    char *token;                                                    // token returned by strtok()
    char *delim = " .,;:!\"?\n";                                    // delimiter characters for strtok()
    char *word;
    Node** Table;

    if (argc <= 1) {
        printf("ERROR: Usage: %s table_size\n", argv[0]);
        return 1;
    }
    htsize = atoi(argv[1]);
    Table = ht_create();
    while (1) {
        if (getline(&line, &length, stdin) == -1)                   // read next line
            break;                                                  // exit loop when no more lines
        token = strtok(line, delim);                                // extract next token from line
        while (token != NULL) {
            word = lowercase(token);                                // store in word a copy of the token in lower-case
            ht_insert(Table, word);                                 // insert word into table
            token = strtok(NULL, delim);                            // extract next token

        }n++;

    }
    ht_print(Table);
    ht_destroy(Table);
    return 0;

}

/* returns an integer for place in Table*/
unsigned int hash(const char *string)
{

    int i;
    unsigned int h = 0U;

    for (i = 0; string[i] != '[=10=]'; i++)
        h = h * HASH_MULTIPLIER + (unsigned char) string[i];

    return h % htsize;
}

/* creates a heap-allocated hash table with htsize buckets */
Node **ht_create(void)
{
    Node** Table;

    Table = (Node**)malloc(sizeof(Node*));                          //allocates memory for size of Table
    Table[0] = (Node*)malloc(sizeof(Node));                         //allocates memory for bucket
    if (Table == NULL)
    {
        fprintf(stderr, "malloc failed.\n");                        //exits program if Table is empty
        exit(0);
    }
    int i = 0;                                                      //initialize int i
    for (i = 0; i <= htsize; i++){                                  //for loop to create htsize buckets
        Table[i] = (Node*)malloc(sizeof(Node));                     //allocates memory for each bucket
        Table[i] -> count = 0;                                      //initilizes count
        Table[i] -> str = " ";                                      //initializes str to empty string
        Table[i] -> next = NULL;                                    //initializes next
    }

    return Table;                                                   //returns hash table
}

/* inserts word into heap allocated hash table*/
int ht_insert(Node **Table, char *word)
{

    int index = hash(word);                                         //runs hash function to create index for entry
    Node* entry = Table[index];                                     //creates nodetype "entry" = the index of the table
                                                                    //previosuly set
    Node* temp = entry;                                             //sets temp nodetype = to entry
    if (entry == NULL)                                              //if the index is empty run body
    {
        Node* newEntry = (Node*)malloc(sizeof(Node));               //allocates memory for the new entry for testing
        if (newEntry == NULL)                                       //if new entry is empty jump to error
        {
            fprintf(stderr, "malloc failed at insert\n");
            return 0;
        }
        newEntry -> next = NULL;                                    //if passed, set next to NULL
        newEntry -> str = word;                                     //make str = word
        if (newEntry -> str == NULL)                                //if the word is empty print error
        {
            fprintf(stderr, "malloc failed at insert\n");
            return 0;
        }
        //strcpy(newEntry -> str, word);                              //if passed, copy word
        newEntry -> count = 1;                                      //set count to 1 to make sure the word entered is atleast 1
        Table[index] = newEntry;                                    //the bucket at i = to new entry
        return 1;
    }
    while (entry != NULL)                                           //if word is already inside of a the table run body
    {

        //if ((entry -> str = strdup(word)) == 0)
        if (strcmp(entry -> str, word) == 0)                        //if word is same as word at current i bucket
        {
            entry -> count++;                                       //add count by 1
            return 1;
        }
        temp = entry;                                               //set temp = entry
        entry = entry -> next;                                      //go to next entry in linked list
    }

    Node* newEntry = (Node*)malloc(sizeof(Node));                   //allocates memory for new entry
    if (newEntry == NULL)                                           // if new entry is empty jump to error
    {
        fprintf(stderr, "malloc failed at insert\n");
        return 0;
    }
    newEntry -> next = NULL;                                        //set next for new entry = null
    newEntry -> str = word;                                         //set new entry str = word
    if (newEntry -> str == NULL)                                    //if new entry str is null jump to error
    {
        fprintf(stderr, "malloc failed at insert\n");
        return 0;

    }
    newEntry -> str = strdup(word);                                 //
    strncpy(newEntry -> str, word, strlen(word) - 1);
    newEntry -> count = 1;
    temp -> next = newEntry;
    return 1;
}

/* prints heap allocated hash table */
void ht_print(Node **Table)
{
    int i = 0;                                                          //initialize i = 0
    Node* entry;                                                        //nodetype entry
    for (i = 0; i < htsize; i++)                                        //for loop to run through each bucket
    {
        entry = Table[i];                                               //entry = ith bucket
        printf("HT[%d]: ", i);                                          //print ith bucket name
        while (entry != NULL)                                           //while there is information in a bucket
        {
            if (entry -> count != 0 && strcmp(entry -> str, " ") > 0)   //if there is an entry and its not an empty string
                printf(" [%s , %d]", entry -> str, entry -> count);     //print str and count
            entry = entry -> next;                                      //move on to next bucket
        }
        printf("\n");
    }
}

/* destroys heap allocated hash table */
void ht_destroy(Node **Table)
{
    int i = 0;                                                          //initialize i = 0
    Node* entry;                                                        //nodetype entry
    Node* temp;                                                         //nodetype temp
    for (i = 0; i < htsize; i++)                                        //for loop to run through each bucket
    {
        entry = Table[i];                                               //entry = ith bucket
        temp = entry;                                                   //temp = entry = ith bucket
        while (entry != NULL)                                           //while entry is not empty: body statement
        {
            if (strcmp(entry -> str, " ") > 0)                          //if str is not an empty string
            {
                temp = entry -> next;                                   //temp = next bucket
                free(entry -> str);                                     //free memory for str in entry
                free(entry);                                            //free up memory for entry
                entry = temp;                                           //entry is temp (next bucket)
            }
        }
    }
    free(*Table);                                                       //Free table
    free(Table);                                                        //free table
}

/*Convert string str to lower-case */
char *lowercase(char *str)
{
    char *word, *ptr;

    if ( (word = strdup(str)) !=  NULL) {
        for (ptr = word; *ptr != '[=10=]'; ptr++)
            *ptr = tolower(*ptr);
    }
    return word;
}

该代码旨在接收一个文本文件,特别是这个文件:

Little Boy Blue,
Come blow your horn,
The sheep's in the meadow,
The cow's in the corn;
Where is that boy
Who looks after the sheep?
Under the haystack
Fast asleep.
Will you wake him?
Oh no, not I,
For if I do
He will surely cry.

产出

HT[0]:  [i?  , -264221488] [under , 1] [oh , 1] [surely , 1]
HT[1]:  [i?  , -264221360] [that , 1]
HT[2]:  [i?  , -264221232] [horn , 1] [meadow , 1] [is , 1] [fast , 1] [asleep , 1]
HT[3]:  [i?  , -264221104] [cow's , 1] [corn , 1] [who , 1] [him , 1] [for , 1] [if , 1] [do , 1]
HT[4]:  [i?  , -264220976] [sheep's , 1] [where , 1] [no , 1] [not , 1]
HT[5]:  [wake , 1] [cry , 1]
HT[6]: 
HT[7]: 
HT[8]:  [under , 1] [oh , 1] [surely , 1]
HT[9]:  [blue , 1] [blow , 1] [looks , 1]
HT[10]: 
HT[11]:  [your , 1] [in , 2]
HT[12]:  [that , 1]
HT[13]:  [little , 1] [haystack , 1] [i , 2]
HT[14]:  [will , 2]
HT[15]: 
HT[16]:  [horn , 1] [meadow , 1] [is , 1] [fast , 1] [asleep , 1]
HT[17]:  [sheep , 1]
HT[18]:  [you , 1]
HT[19]:  [come , 1] [the , 6]
HT[20]:  [cow's , 1] [corn , 1] [who , 1] [him , 1] [for , 1] [if , 1] [do , 1]
HT[21]:  [after , 1]
HT[22]:  [boy , 2] [he , 1]

正确输出

HT[0]: [under, 1] [oh, 1]
HT[1]: [that, 1]
HT[2]: [meadow, 1]
HT[3]: [cow's, 1] [for, 1] [if, 1]
HT[4]: [sheep's, 1] [where, 1] [no, 1] [not, 1]
HT[5]: [wake, 1] [cry, 1]
HT[6]:
HT[7]:
HT[8]: [surely, 1]
HT[9]: [blue, 1] [blow, 1] [looks, 1]
HT[10]:
HT[11]: [your, 1] [in, 2]
HT[12]:
HT[13]: [little, 1] [haystack, 1] [i, 2]
HT[14]: [will, 2]
HT[15]:
HT[16]: [horn, 1] [is, 1] [fast, 1] [asleep, 1]
HT[17]: [sheep, 1]
HT[18]: [you, 1]
HT[19]: [come, 1] [the, 6]
HT[20]: [corn, 1] [who, 1] [him, 1] [do, 1]
HT[21]: [after, 1]
HT[22]: [boy, 2] [he, 1]

我在使用 xcode 和 gdb 的 mac 上,我不确定如何检查哪里出了问题。任何帮助将不胜感激。

谢谢

EDIT1: 在 ht_create() 函数中完成,将 Table 数组元素初始化为 NULL,这在初始 post 中丢失了。
EDIT2: 完成更新修改后的 ht_print() 和 ht_destroy() 函数。

Node **ht_create(void)
{
    Node** Table;

    // Allocating array (of size htsize) of Node pointers
    Table = (Node**)malloc(htsize * sizeof(Node*)); <-- NOTE: Change done here, used htsize for allocation
    //Table[0] = (Node*)malloc(sizeof(Node)); <-- NOTE: Commented this line, stray code, Table[0] will be allocated in for() loop

    if (Table == NULL)
    {
        fprintf(stderr, "malloc failed.\n"); //exits program if Table is empty
        exit(0);
    }

    // NOTE: Code added for Table[i] NULL initialization
    int i = 0;
    for (i = 0; i < htsize; i++){
        Table[i] = NULL;
    }

    return Table;
}

int ht_insert(Node **Table, char *word)
{
    int index = hash(word);
    Node* entry = Table[index];
    Node *temp;
    if (entry == NULL)
    {
        // First entry at Table[index]
        Node* newEntry = (Node*)malloc(sizeof(Node));
        if (newEntry == NULL)
        {
            fprintf(stderr, "malloc failed at insert\n");
            return 0;
        }

        newEntry->word = strdup(word); <-- NOTE: Change here to use strdup()
        if (newEntry->word == NULL)
        {
            fprintf(stderr, "strdup() failed at insert\n");
            free(newEntry);
            return 0;
        }
        newEntry->count = 1;
        newEntry->next = NULL;

        Table[index] = newEntry;

        return 1;
    }

    // Go to the end of list at Table[index]
    // Also check if input word is same as one existing entry in the list at Table[index], if yes, increase repeat count for the word
    while (NULL != entry)
    {
        // Check if input word is same as word stored in current node
        if (0 == strcmp(word, entry->word))
        {
            entry->count++;

            return 1;
        }

        temp = entry;
        entry = entry->next;
    }

    // New entry in the list at Table[index]    
    Node* newEntry = (Node*)malloc(sizeof(Node));
    if (newEntry == NULL)
    {
        fprintf(stderr, "malloc failed at insert\n");
        return 0;
    }

    newEntry->word = strdup(word);
    if (newEntry->word == NULL)
    {
        fprintf(stderr, "strdup() failed at insert\n");
        free(newEntry);
        return 0;
    }

    newEntry->count = 1;
    newEntry->next = NULL;

    temp->next = newEntry;

    return 1;
}

/* prints heap allocated hash table */
void ht_print(Node **Table)
{
    int i = 0;                                                          //initialize i = 0
    Node* entry;                                                        //nodetype entry
    for (i = 0; i < htsize; i++)                                        //for loop to run through each bucket
    {
        entry = Table[i];                                               //entry = ith bucket
        printf("HT[%d]: ", i);                                          //print ith bucket name
        while (entry != NULL)                                           //while there is information in a bucket
        {
            if (entry->word != NULL)   //if there is an entry and its not an empty string
                printf(" [%s , %d]", entry->word, entry -> count);     //print str and count
            entry = entry -> next;                                      //move on to next bucket
        }
        printf("\n");
    }
}

/* destroys heap allocated hash table */
void ht_destroy(Node **Table)
{
    int i = 0;                                                          //initialize i = 0
    Node* entry;                                                        //nodetype entry
    Node* temp;                                                         //nodetype temp
    for (i = 0; i < htsize; i++)                                        //for loop to run through each bucket
    {
        entry = Table[i];                                               //entry = ith bucket
        temp = entry;                                                   //temp = entry = ith bucket
        while (entry != NULL)                                           //while entry is not empty: body statement
        {
            temp = entry -> next;                                   //temp = next bucket
            if (entry -> word != NULL)                          //if str is not an empty string
            {
                free(entry -> word);                                     //free memory for str in entry
            }
            free(entry);                                            //free up memory for entry
            entry = temp;                                           //entry is temp (next bucket)
        }
    }
    free(Table);                                                        //free table
}