seg faults with lists

ok, so im getting a seg fault when im trying to add to a list.

what im trying to do is get a list of pointers to players (or the class they inherit from to avoid a dependency loop).

first in main im creating my room object and my player object (as well as setting various strings (yes im using cstrings)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    room* myRoom = new room("My Room");

//setting up some other stuff

    character *player = new character("Tester");

//setting up the player
//Now I want to add the player to the room so i pass the rooms function a pointer to the player object to be contained in a list.

    myRoom->addChar(player);

//now that runs

void room::addChar(thingWithStuff* _Char){
    printf("putting %s in %s.\n",_Char->getName(),getName());
    this->charList.push_back(_Char);
}

i put the printf line in for debug purposes (yeah i know i can just get them from gdb)

charList is a protected member of class room

now when i run it i get
1
2
3
zlg $ ./zlg 
putting Tester in My Room.
Segmentation fault

so its its trying to put the right character into the right room.

running gdb gives me this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

(gdb) run
Starting program: 
putting Tester in My Room.

Program received signal SIGSEGV, Segmentation fault.
0xb7e4b667 in std::_List_node_base::hook ()
   from /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/libstdc++.so.6
(gdb) where
#0  0xb7e4b667 in std::_List_node_base::hook ()
   from /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/libstdc++.so.6
#1  0x080498e1 in std::list<thingWithStuff*, std::allocator<thingWithStuff*> >::_M_insert (this=0x804d078, __position={_M_node = 0x804d078}, __x=@0xbfebff80)
    at /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/include/g++-v4/bits/stl_list.h:1140
#2  0x0804991e in std::list<thingWithStuff*, std::allocator<thingWithStuff*> >::push_back (this=0x804d078, __x=@0xbfebff80)
    at /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/include/g++-v4/bits/stl_list.h:761
#3  0x080491c6 in room::addChar (this=0x804d008, _Char=0x804d108)
    at src/game/room.cpp:93
#4  0x080488f8 in main () at src/main.cpp:45 


can anyone provide any advice? im very unsure how to proceed from here.
I see only 2 possible reasons for this problem:
(1) The element it tries to add is not present
(2) The List declaration is problematic

In this case, we know that the element it tries to add (_Char) is present, so the problem cause will be the declaration of List.

How did you declare this List?
Where (in which class and tell about class hierarchy) did you declare this List?

Last edited on
in the header file for room
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class room : public thingWithStuff {
    public:

//member functions

    private:
        room *ptr_North;
        room *ptr_South;
        room *ptr_East;
        room *ptr_West;

        std::list<thingWithStuff*> charList;

};


should i have done something to initialise it somewhere, like in the constructor?
Last edited on
Yes, you will need to have called the contructor for charList in the constructor of room.

As a second issue, player is a pointer to character, not thingWithStuff
Last edited on
To make it simple and working,

Method 'addChar' should receive it as an instance of 'character' class and declare the 'List' as a list of 'character's.
thanks, how would i do that?

i suppose
changing that to a pointer to a list and then putting
*charList = new std::list<thingWithStuff*>;
in the constructor would work i guess, but is that the only way to initialise it?

with something else i would just say var=0;

should i perhaps say
1
2
3
4
room(){
//anything else i want in the constructor
charList.list();
}


player is derived from thingWithStuff

thanks very much for the help.

Edit:
Vengateshs: i was going to do that until i realised that it would create a dependency loop as my character class also has a pointer to a room. i figured that giving the room a list of pointers to the base class would be a simple solution.

if that breaks anything then i can just dynamic_cast it.
that said ive been wondering how this may affect the functionality of my player... i suppose it depends on how i call it.
Last edited on
I understood you are doing a Hierarchical Inheritance (Derived 'room' and 'character' from a single base class).
Does it work on doing a 'dynamic_cast' to the specific type while adding to the List?
the compiler doesnt seem to mind it (but then the compiler didnt mind when i was just telling it to insert a pointer to a derived class into a list of pointers to the base class) but im still getting the seg fault, so im guessing im not initialising the list properly

that last attempt was with
1
2
 19     std::list<thingWithStuff*> l;
 20     charList = l;

in the constructor.

hmmm, if i was to make that &charList = &l would charList be deleted when the constructor ends?

in any case, i was running it like that because
changing std::list<thingWithStuff*> charList; to std::list<thingWithStuff*>* charList; and adding charList = new std::list<thingWithStuff*>; to the constructor breaks it. well, that line itself works but gives me a bunch of errors down the track to deal with. thought it wouldnt hurt to try what i just have first cause if this doesnt work then it could mean ive changed a bunch of stuff i didnt need to and may have to change back.

i should setup an svn server.....

EDIT:
hmmm
i put charList = std::list<thingWithStuff*>::list(); in the constructor. still seg faults

EDIT 2:
lololol
i put

1
2
 22    thingWithStuff *lol=0;
 23    charList.push_back(lol);


in the constructor and suddenly the error changes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/zlg $ ./zlg 
putting lol2? in My Room.
*** glibc detected *** ./zlg: malloc(): memory corruption (fast): 0x0804d088 ***
======= Backtrace: =========
/lib/libc.so.6[0xb7da5950]
/lib/libc.so.6[0xb7da7c2a]
/lib/libc.so.6(malloc+0x7e)[0xb7da937e]
/usr/lib/gcc/i686-pc-linux-gnu/4.1.1/libstdc++.so.6(_Znwj+0x29)[0xb7f4e439]
./zlg[0x8049926]
./zlg[0x8049949]
./zlg[0x804995e]
./zlg[0x80499be]
./zlg[0x8049a10]
./zlg[0x804920c]
./zlg(__gxx_personality_v0+0x2a1)[0x8048941]
/lib/libc.so.6(__libc_start_main+0xd8)[0xb7d57838]
./zlg(__gxx_personality_v0+0x61)[0x8048701]
======= Memory map: ========
08048000-0804c000 r-xp 00000000 03:03 20119553   build/0.1/zlg
0804c000-0804d000 rw-p 00003000 03:03 20119553   build/0.1/zlg
0804d000-0806e000 rw-p 0804d000 00:00 0          [heap]
b7c00000-b7c21000 rw-p b7c00000 00:00 0 
b7c21000-b7d00000
b7d41000-b7d42000 rw-p b7d41000 00:00 0 
b7d42000-b7e65000 r-xp 00000000 03:03 32915934   /lib/libc-2.5.so
b7e65000-b7e66000 r--p 00122000 03:03 32915934   /lib/libc-2.5.so
b7e66000-b7e68000 rw-p 00123000 03:03 32915934   /lib/libc-2.5.so
b7e68000-b7e6b000 rw-p b7e68000 00:00 0 
b7e6b000-b7e75000 r-xp 00000000 03:03 32784389   /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/libgcc_s.so.1
b7e75000-b7e76000 rw-p 00009000 03:03 32784389   /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/libgcc_s.so.1
b7e76000-b7e99000 r-xp 00000000 03:03 32915928   /lib/libm-2.5.so
b7e99000-b7e9b000 rw-p 00022000 03:03 32915928   /lib/libm-2.5.so
b7e9b000-b7f71000 r-xp 00000000 03:03 32784903   /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/libstdc++.so.6.0.8
b7f71000-b7f74000 r--p 000d5000 03:03 32784903   /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/libstdc++.so.6.0.8
b7f74000-b7f76000 rw-p 000d8000 03:03 32784903   /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/libstdc++.so.6.0.8
b7f76000-b7f7d000 rw-p b7f76000 00:00 0 
b7f94000-b7f95000 rw-p b7f94000 00:00 0 
b7f95000-b7faf000 r-xp 00000000 03:03 32915525   /lib/ld-2.5.so
b7faf000-b7fb0000 r--p 00019000 03:03 32915525   /lib/ld-2.5.so
b7fb0000-b7fb1000 rw-p 0001a000 03:03 32915525   /lib/ld-2.5.so
bfdd1000-bfde7000 rw-p bfdd1000 00:00 0          [stack]
ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]
Aborted


EDIT 3:
lol k.
ive now tried push_back() and assign() (which got the malloc() failure).

for reference i looked through a program i wrote whilst going through a teach yourself c++ book as an example and i had used vectors this way with push_back() or reserve() (which i notice lists dont have.) in the class that they are members off's constructors.

i guess next im doing the new allocation... but i think ill have a break first.
Last edited on
Are you trying something like the one below?
If so, you may get some clue on seeing the output from addChar() method. :-)


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
#include<iostream>
#include<stdio.h>
#include<conio.h>
#include<list>

using namespace std;

class thingWithStuff {
        std::string Name;    
    public:
    thingWithStuff() { this->Name = "default-thingWithStuff";}
    thingWithStuff(string s) { this->Name = s;}    
    std::string getName();        
};

class room : public thingWithStuff {
        std::list<thingWithStuff*> charList;
        std::string Name;
    public:
    room() { this->Name = "default-room";}
    room(string s) { this->Name = s;}     
    std::string getName();
    void addChar(thingWithStuff*);
};

class character : public thingWithStuff {
        std::string Name;
    public:
    character() { this->Name = "default-character";}
    character(string s) { this->Name = s;}    
    std::string getName();
};

std::string thingWithStuff::getName() {
    return Name;
}
std::string room::getName() {
    return Name;
}
void room::addChar(thingWithStuff* _Char){
    cout << _Char->getName() << endl;
    cout << getName();    
    this->charList.push_back(_Char);
}
std::string character::getName() {
    return Name;
}

int main()
{
    room* myRoom = new room("My Room");
    character *player = new character("Tester");
    myRoom->addChar(player);
    getch();
    return 0;
}
hmmmm
why does that compile (after removing #inculde <conio.h> and getch(); (conio.h is a dos lib that doesnt exist in linux... interestingly enough i was planing on implementing ncurses, which is a fork of a port i believe, somewhere along the way) and run without problem.....

its doing practically the same thing.

...

hahaha

so i go to post a cut down version of what im doing, then think i may as well make it compilable. so put in some of the implementation i had taken out in as short as i can (in class definitions for the most part) and then compile it.
sall good.
i run it and dont have any problems.

well, at least im amused by it as opposed to extremely frustrated.

in any case, here is the cut down version of my program.
the destructors are commented cause i didnt provide implementation for them.
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
#include <list>
#include <cstring>

const int MAX_NAME_LENGTH=20; //or something
const int MAX_DSC_LENGTH=50; //or something

enum thingtype {THING, THINGWITHSTUFF, ITEM, ROOM, CHARACTER};


class thing{
    public:
        // constructor
        thing();
        thing(const char *name);
     //   thing(const thing &c);
        // destructor
       // virtual ~thing();

//some other stuff

        //m_Names ref funcs
        void setName(const char *name);
        const char *getName(void) const;
        //m_Disc ref funcs
        void setDisc(const char *disc);
        const char *getDisc(void) const;

//some other stuff

    protected:
        char m_Name[MAX_NAME_LENGTH];
        char m_Disc[MAX_DSC_LENGTH];

// some other stuff

        thingtype ThingType;
};

thing::thing(){
    ThingType=THING;
}

thing::thing(const char *name){
    setName(name);
    thing();
}
void thing::setName(const char *name){
    strcpy(m_Name, name);
}

const char *thing::getName(void) const{
    return m_Name;
}

void thing::setDisc(const char *disc){
    strcpy(m_Disc, disc);
}

const char *thing::getDisc(void) const{
    return m_Disc;
}

class item : public thing {
    public:
        //constructors
        item(){ThingType=ITEM;}
        item(const char *name):thing(name){item();}
};
typedef std::list<item*> inventory;


class thingWithStuff: public thing{
    public:
        //constructors
        thingWithStuff(){ThingType=THINGWITHSTUFF;}
        thingWithStuff(const char *name):thing(name){thingWithStuff();};
 //       virtual ~thingWithStuff();


//other stuff (actually another list, but not one i had started to test. ill cross
//that bridge when i come to it(which should be easer cause im implementing it the
//same way i am the one that currently causing problems (its a list of a third class
//derived from thing (i sware there is a method to my madness))))
   private:
        //inventory inventory;
        inventory inv;

};

class room : public thingWithStuff {
    public:
        //constructor
        room();

        room(const char *name);

        //destructor
//        virtual ~room();

//and our addChar class that seems to be where we are getting all our problems 
        //add character to the list
        void addChar(thingWithStuff* _Char);

    private:
        room *ptr_North;
        room *ptr_South;
        room *ptr_East;
        room *ptr_West;

// i seem to remember that being protected instead of private. no matter
// my list, declared exactly the same way you have yours.
        std::list<thingWithStuff*> charList;

};
//rooms default constructor. notice all the things ive tried to do in it
room::room(){
    ptr_North=0;
    ptr_South=0;
    ptr_East=0;
    ptr_West=0;
    ThingType=ROOM;
  //  std::list<thingWithStuff*> l;
   // charList = std::list<thingWithStuff*>::list();
   //charList.list();
   //thingWithStuff *lol;
//  charList.push_back(lol);
 // charList.assign(1, lol);
}

//the constructor that im calling, which happens to call the default one anyway.
//if you had done something with your constructor then i would have thought that
//the problem lay here... 
room::room(const char *name):thingWithStuff(name){
    room();
}

//implementation for addChar()
//i use printf instead of cout, but for all intents and purposes they are the same.
//it seg faults on the push_back() line.
//the commented line has the dynamic_cast you asked about i believe. either line works.
void room::addChar(thingWithStuff* _Char){
    printf("putting %s in %s.\n",_Char->getName(),getName());
    this->charList.push_back(_Char);
//    this->charList.push_back(dynamic_cast<thingWithStuff*>(_Char));
}

class character : public thingWithStuff{
    public:
        //constructors
        character(){ThingType=CHARACTER;}
        character(const char *name):thingWithStuff(name){character();}

        //destructor
//        virtual ~character();

//some other stuff

};

int main(){

    room* myRoom = new room("My Room");
    myRoom->setDisc("a test room");

    character *player = new character("Tester");

    myRoom->addChar(player);

    delete myRoom;
    delete player;
puts("ZOMG I GOT TO THE END");
    return 0;
}



well that's brilliant. now i have absolutely no idea what's going on.

EDIT:
ok, so im guessing that im doing something in a bad way somewhere and its dieing.
perhaps my strings. i have a few others for discriptions.
i am also sporting a second (or first) list of items* (a class derived from thing)

the rooms have pointers to other rooms. the character has a pointer to a room.

could these cause problems?

EDIT 2: just tested the strings twice. dont think thats it.

EDIT 3: and now ive added in my second list... still no seg fault

EDIT 4: and it turns out im doing bad things with c style strings. cause i had fixed length strings i was causing a buffer overflow.

thanks everyone for the help.
Last edited on
Topic archived. No new replies allowed.