Hashtable bad EXC_BAD_ACCESS error

Hello everyone, I'm writing a hashtable for an exercise.
I am nearly finished but unfortunately I get a exc_bad_access error.
Now I am stuck for more than two days and since I am not able to find/understand the problem I hope to get a little bit help from you guys.
The idea is to have a bucket array of the class linked list.
In this bucket array each list signifies a linked list that stores the elements: name and mass.

For me it seems that something is wrong with my bucket declaration.
Thank you for any advise.
header.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
//
//  header.h
//  ex3
//
//  Created by Georg Pollak on 19.11.12.
//  Copyright (c) 2012 Georg Pollak. All rights reserved.
//

#ifndef __ex3__header__
#define __ex3__header__

#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <string>

using namespace std;
class test{
    
    int y;
};

// elements we want to store in the queue------------------------------
class element{
public:
    int set_element(string name_n, float mass_n);
    float get_mass();
    string get_name();

private:
    string name;
    float mass;
};

// minimal linked list (queue)-----------------------------------------
class node{
public:
    // constructor
    node();  // constructors have the same name as the class
    // and no return value.
    // another constructor, with one argument
    // (using function overloading, also works inside classes)
    //zeiger auf sich selbst
    node(node *n);
    // destructor
    ~node(); // destructor: beginning with ~, no arguments (ever)
    // member functions
    element *get_item();
    node *get_next();
    node *return_next();
    int set_item(element x);
    int set_next(node *n);
private:
    element *item;
    node *next;
};


class linked_list{
public:
    linked_list();
    ~linked_list();
    int push(element x);
    int pop();    
    int hash(string s);
    int make_table(int arg_num, char *arg_var[]);
    node *get_anchor();
private:
    linked_list **bucket;
    node *anchor;
};

#endif /* defined(__ex3__header__) */ 

implementation.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
//
//  header.cpp
//  ex3
//
//  Created by Georg Pollak on 19.11.12.
//  Copyright (c) 2012 Georg Pollak. All rights reserved.
//

#include "header.h"


using namespace std;

// member functions implementation element-----------------------------

int element::set_element(string name, float mass){
    this->name = name;
    this->mass = mass;
    return 0;
}


float element::get_mass(){
    return this->mass;
}

string element::get_name(){
    return this->name;
}

// member functions implementation node--------------------------------
//constructor
node::node(){
    item = NULL;
    next = NULL;
}

//Construction of a new List node n

node::node(node *n){
    item = NULL;
    next = n;
}

// destructor
//Is called when the scope of the Object is lost
node::~node(){
}

//returns a pointer to the elment item of node n [e.g. node.get_item();] => acess of variable of element of node n
element *node::get_item(){
    return item;
}

//returns a pointer to a node [e.g. node.get_next();]
node *node::get_next(){
    return next;
}

node *node::return_next(){
    return next;
}

int node::set_item(element x){
    item = &x;
    return 0;
}

//set a new node from current node (if it is the last) [e.g. lastnode.set_next(newnode);] => pointer of lastnode points to next node
int node::set_next(node *n){
    if (next != NULL){
        // we already have a next one, not at the end
        // cannot add here
        return 1;
    }
    next = n;
    return 0;
}

// member functions implementation linked_list--------------------------
linked_list::linked_list(){
    anchor = NULL;
    bucket = new linked_list *[5];   // I AM NOT SURE IF THIS WORS AS I HOPE
    for (int i=0; i<5; i++){
        bucket[i] = NULL;
    }
}
//HERE COMES THE PLACE WHERE THE DEBBUGER SHOWS ME THE ERROR OF THE NODE ANCHOR
//IF I CALL PUSH WITH THE BUCKET IN MAKE_TABLE
int linked_list::push(element x){
    node *n = new node;
    n->set_item(x);
    n->set_next(anchor);  // Thread 1:EXC_BAD_ACCESS(code=1, address=0x8) error!!?
    anchor = n;
    return 0;
}

//Simple Hashfunction(works!)
int linked_list::hash(string s){
    int const FACTOR = 101;
    int const MAX =5;
    int sum = 0;
    for(unsigned int i=0; i < s.length(); ++i){
        sum += s[i] * FACTOR;
        sum %= MAX;
    }
    return sum;
}

node *linked_list::get_anchor(){
    return this->anchor;
}

int linked_list::make_table(int arg_num, char *arg_var[]){
    
    if(arg_num != 2){
        cout << "usage: " << arg_var[0] << " filename" << endl;
        return 1;
    }
    
    // the data
    int i = 0;
    string name;
    float mass;
    
    {
        //fin(arg_var[1]); = fin.open(argv[1], ios::in);
        ifstream fin(arg_var[1]);
        if (!fin.is_open()){
            cout << "error opening file: " << arg_var[1] << endl;
            return 1;
        }                                       //.is_open(): The function returns true if a previous call to open succeeded
        
        stringstream inp;                       // create the stream for the data without the comments
        string s;                               // and a buffer to read in
        //stringstream provides an interface to manipulate strings
        
        // read in the whole file
        while(true){
            getline(fin, s);                    //getline(): extracts characters from fin and stores them into s
            //eof(): end of line
            s = s.substr(0, s.find('#'));       // get rid of everything right to the #
            if (s!="")                          //stringstream << : Insert data with format (zwischenspeicher)
                inp << s << endl;
            if(fin.eof()) break;                //substr(pos, npos): returns a string object with its contents initialized to a substring of the current object
        }                                       //pos: position of a character in the current string object to be used as starting character for the substring.
        //n: length of the substring. / find(): searches for the content and returns position / if something left, add to the stream
        fin.close();
        
        // now read in as normal / stringstream >> x: Extract formatted data into x
        
        /*if (!(inp >> d1[i] >> d2[i])){
         cout << "error while reading in data" << endl;
         return 1;
         }*/
        //make hash_table
        //We have alread checked in the beginning that no empty list is submitted!
        node test;
        while(!inp.eof()){
            //reads in strings & floats
            inp >> name >> mass;
            element x;
            x.set_element(name, mass);
            //make_table
            
//SHOULD MAKE A HASHTABLE OUT OF 5 LINKED LISTS AND STORES THE ELEMENTS X IN THE //CORRECT BUCKET. HERE IS THE PLACE WHERE BUCKET CALLS PUSH AND THAN I GET THE ERROR 
            bucket[hash(name)]->push(x);
            i+=1;
        }
    }
    return 0;
    // do whatever you wanted to do with the data...
}


linked_list::~linked_list(){
    
}

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//
//  main.cpp
//  ex3
//
//  Created by Georg Pollak on 19.11.12.
//  Copyright (c) 2012 Georg Pollak. All rights reserved.
//

#include <iostream>
#include "header.h"
using namespace std;


int main(int argc, char * argv[])
{
    linked_list my_list;
    my_list.make_table(argc, argv);
    
    return 0;
}
1
2
3
4
int node::set_item(element x){
    item = &x;
    return 0;
}


x only exists for the scope of the function, therefore the value held by item is only valid for the scope of the function. Once the function returns item points to memory that no longer holds an element.

The typical implementation of a linked list stores a copy of the element inserted, not a pointer to it.
Ok thanks, that makes sense.
So I changed item to an normal element but I still get the EXC_BAD_ACCESS error.
I also tried to make name and mass public to fill it directly.
So the error seems to come from somewhere else:(
1
2
//SHOULD MAKE A HASHTABLE OUT OF 5 LINKED LISTS AND STORES THE ELEMENTS X IN THE //CORRECT BUCKET. HERE IS THE PLACE WHERE BUCKET CALLS PUSH AND THAN I GET THE ERROR 
            bucket[hash(name)]->push(x);


Fist, make_table has no business in your linked_list implementation.
Second, linked_list has no business having a member named bucket.

The only manipulation to bucket prior to this is to allocate space for 5 pointers and set them to NULL. Here, you dereference those NULL pointers.
I goooooot it:)
Thank you soooo much took me so long to figure this out.

I wrote a new class hash_table, than it worked.

1
2
3
4
5
6
7
8
class hash_table{
public:
    int hash(string s);
    int make_table(int arg_num, char *arg_var[]);
    int print_table();
//private:
    linked_list bucket[5];
};
Topic archived. No new replies allowed.