Linux中的Segfault在Mac OS上运行良好

时间:2015-09-29 03:58:13

标签: c++ linux macos segmentation-fault

我正在进行C ++家庭作业,我们必须在其中构建单链表的哈希表。我已经在Mac上编写了我的代码 - 它可以很好地编译并完美地生成预期的输出。但是,当我在Linux中运行程序时,我得到了段错(核心转储)。使用gdb进行调试时,我收到消息

Program received signal SIGSEGV, Segmentation fault.
__strcmp_sse2 () at ../sysdeps/x86_64/multiarch/../strcmp.S:210
210 ../sysdeps/x86_64/multiarch/../strcmp.S: No such file or directory.

我在本网站上的其他帖子中读到,在这种情况下gdb会产生误导,而且问题与“strcmp”功能无关。但是,我无法查看代码中的问题所在。如果有人能指出我正确的方向,那将非常感激。 TIA。

//string_set.cpp

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

#include "string_set.h"

using namespace std;

string_set::string_set() {

    for (int i = 0; i < HASH_TABLE_SIZE; i++) { //initializing empty hash table
        hash_table[i] = NULL;
    } //end for

    iterator_index = 0;
    iterator_node = hash_table[iterator_index];
}

void string_set::add(const char *s) {

    int hash_val = hash_function(s);

    if (contains(s) == 1) {
        throw duplicate_exception();
    } //end if

    node *a = new node;
    if (a==NULL) {
        throw memory_exception();
    } //end if
    a->s = new char[strlen(s) + 1];
    if (a == NULL) {
        delete a;
        throw memory_exception();
    } //end if
    strcpy(a->s, s);

    a->next = hash_table[hash_val];
    hash_table[hash_val] = a;

    if (contains(s) == 0) {
        throw memory_exception();
    } //end if
    else {
        reset();
    } //end else

}

void string_set::remove(const char *s) {

    if (contains(s) == 0) {
        throw not_found_exception();
    } //end if

    int hash_val = hash_function(s);

    node *prev = new node;
    prev = hash_table[hash_val];
    node *ptr = new node;
    ptr = hash_table[hash_val];

    while (strcmp(ptr->s, s) != 0) { // 
        prev = ptr;
        ptr = ptr->next;
    } //end while
    if (prev == ptr) { //if node to be deleted is first in list
        hash_table[hash_val] = ptr->next;
    } //end if

    delete ptr->s;
    prev->next = ptr->next;
    delete ptr;

    reset();

}

int string_set::contains(const char *s) {

    int hash_val = hash_function(s);

    node *ptr = new node;
    ptr = hash_table[hash_val];

    while (ptr != NULL) {
        if (strcmp(s, ptr->s) == 0) { // 
            delete ptr;
            return 1;
        } //end if
        else {
            ptr = ptr->next;
        } //end else
    } //end while

    return 0;
}

void string_set::reset() {

    iterator_index = 0;
    iterator_node = hash_table[iterator_index];

}

const char *string_set::next() {

    if (iterator_node != NULL) {
        char copy[strlen(iterator_node->s) + 1];
        strcpy(copy, iterator_node->s);
        iterator_node = iterator_node->next;
        return copy;
    } //end if

    while (iterator_index < HASH_TABLE_SIZE - 1) {
        while (iterator_node == NULL) {
            ++iterator_index;
            iterator_node = hash_table[iterator_index];
            if ((iterator_index == HASH_TABLE_SIZE - 1) && (iterator_node == NULL)) {
                return NULL;
            }
        } //end nested while
        char copy[strlen(iterator_node->s) + 1];
        strcpy(copy, iterator_node->s);
        iterator_node = iterator_node->next;
        return copy;

    } //end while

    return NULL;

}

string_set::~string_set() {

    reset();

    node *ptr = new node;
    ptr = iterator_node;

    while (ptr != NULL) {
        delete ptr->s;
        next();
        ptr = iterator_node;
    } //end while

    delete ptr;
}

int string_set::hash_function(const char *s) {

    int sum = 0;

    for (unsigned int ind = 0; ind < strlen(s); ind++) { //summing elements in string s
        sum += s[ind];
        sum = sum % HASH_TABLE_SIZE;
    } //end for

    return sum % HASH_TABLE_SIZE;
}

string_set.h

using namespace std;

class string_set {
public:
/*Purpose
    initialize the set to contain no elements
* Preconditions
    none
* Exceptions
    none
*/
string_set();

/*Purpose
*   add s to the set
*   if s is successfully added, reset the iterator
* Preconditions
*   s is a legal string
* Exceptions
*   if s is already present then throw duplicate_exception
*   else if s there is not enough memory to add s then throw memory_exception
*/
void add(const char *s);

/*Purpose
*   remove s from the set
*   if s is successfully removed, reset the iterator
* Preconditions
*   s is a legal string
* Exceptions
*   if s is not present then throw not_found_exception
*/
void remove(const char *s);

/*Purpose
*   return 1 if s is in the set and 0 otherwise
* Preconditions
*   s is a legal string
* Exceptions
*   none
*/
int contains(const char *s);

/*Purpose
*   reset the iterator to the first element
* Preconditions
*   none
* Exceptions
*   none
*/
void reset();

/*Purpose
*   return a pointer to the next set element
*   return NULL if no more elements remain
* Preconditions
*   none
* Exceptions
*   none
*/
const char *next();

/*Purpose
*   delete all dynamically allocated memory
* Preconditions
*   none
* Exceptions
*   none
*/
~string_set();
private:
/*Purpose
*   return the hash value h associated with s
*   h must consist of: (sum of the characters in s) mod HASH_TABLE_SIZE
* Preconditions
*   s is a legal string
* Exceptions
*   none
* Examples
*   hash_function("a") returns 97
*   hash_function("ab") returns 95
*   hash_function("ba") returns 95
*   hash_function("") returns 0
*/
int hash_function(const char *s);

enum {HASH_TABLE_SIZE = 100};

class node {
    public:
    char *s;
    node *next;
};

// hash_table[i] is the head of a linked list of nodes
node *hash_table[HASH_TABLE_SIZE];

// iterator position
int iterator_index; // index in hash_table
node *iterator_node; // node in hash_table[iterator_index];
};

class duplicate_exception { };
class memory_exception { };
class not_found_exception { };

1 个答案:

答案 0 :(得分:0)

contains函数中的以下代码行:

   if (strcmp(s, ptr->s) == 0) { // 
        delete ptr;

将删除刚找到的节点的内存,当您稍后尝试使用该节点时,会导致未定义的行为。

在代码的几个地方,你为一个指针分配一个新节点,然后立即将指针指向另一个位置 - 这将导致内存泄漏,并可能导致你删除你不想要的东西。

node *ptr = new node;
ptr = hash_table[hash_val];

应该是

node *ptr = hash_table[hash_val];

然后不需要相应的delete(除非您实际上是删除了节点)。