Using a member within a pointer function(that is located in the same class)- segfault

I'm currently programming a server which uses multiple threads- I have a class for one map in the game. Each map has a thread for timed events(tile regeneration, NPC regeneration, etc.), and a thread for handling NPCs(movement, combat, etc.). A basic structure of the class looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
class Region {
public:
    /* game values are here, they are public so
    they can be accessed from outside of the class
    inside of packet-handling functions and such */
    int value;
    
    void *Function();
    
    //there are more functions, but this is just to give you an idea.
    Region();
};


Inside of region.cpp, it looks like this:

1
2
3
4
5
6
7
8
9
10
Region::Region() {
    value = 0;
}

void *Region::Function() { 
//note this is not the actual code, I am just showing an example of using class members
    while(true) {
        value++;
    }
}


The program crashes when I use a member of the same class the function is located in- in the context I have shown about it would crash on "value++". Do any of you guys know how to fix this?
closed account (18hRX9L8)
1
2
while(true)
{value++;}

That's an infinite loop.
Last edited on
Given that a particular object variables are referenced with respect to the this pointer - the thing that springs immediately to mind is bad this pointer.


a. you are accessing the object through an unitialized pointer.

b. You have an array of objects (probably aloocated from the heap using the new operator) and you have tried to access beyond the bounds of that array.

c. You are using a bad iterator on a container.


But we might need a look at your code to pinpoint the exact error
@usandfriends
It is meant to be- that wouldn't cause a crash regardless. As I said in the original post, it is to show using a value from the class. The two functions are to handle NPCs and to handle timed events. They are supposed to be infinite until the program exits.
Last edited on
@guestgulkan

Here's my code- I'll keep out the includes and defines.

region.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
class Region {
public:
    std::vector<NPC>mapNPCvector;
    std::vector<Projectile>mapProjectileVector;
    std::vector<RegenTile>mapRegenTiles;
    std::vector<RegenNPC>mapRegenNPCs; 
    std::vector<Conversation>NPCdialogueVector;
    std::vector<Bank>bankVector;
    
    unsigned char tileMap[320][320][5];
    bool tileCollisionMap[320][320];
    bool tileChangeMap[320][320];
    //Conversation NPCdialogueMap[320][320];
    
    int mapWeatherType;
    Delay mapWeatherGen;  
    
    std::string name;
    int mapID;
    
    ALLEGRO_EVENT_QUEUE *eventQueue1, *eventQueue2;
    ALLEGRO_EVENT event1, event2;
    ALLEGRO_TIMER *gameTimer;
    
    //functions
    
    void changeTile(int tile, int layer, int x, int y, bool changeMapChange);
    
    void setName(int);
    void loadMap(const char *);
    void loadDialogue(const char *);
    
    void *timedAllegroEvents();
    void *handleMapNPCs();
    
    static void *timedAllegroEventsHelper(void *context) {
        return((Region *)context)->timedAllegroEvents();
    }
    static void *handleMapNPCsHelper(void *context) {
        return((Region *)context)->handleMapNPCs();
    }
    
    void Initialize();
    Region();    
    ~Region();  
};


region.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
Region::Region() {
    for(int x = 0; x < 320; x++) {
        for(int y = 0; y < 320; y++) {
            for(int z = 0; z < 5; z++)
                tileMap[x][y][z] = 0;  
            
            tileCollisionMap[x][y] = false;
            tileChangeMap[x][y] = false;      
        }        
    }      
    
    mapWeatherType = SUNLIGHT;
    mapWeatherGen.setDelay((int)rand() % 20000 + 10000);    
    
    eventQueue1 = NULL;
    eventQueue2 = NULL;
    gameTimer = NULL;
    
    mapID = MAP_OVERWORLD;
    name = "";
}

void Region::Initialize() {
    gameTimer = al_create_timer(1.0 / 60);
    
    eventQueue1 = al_create_event_queue();
    eventQueue2 = al_create_event_queue();
    
    al_register_event_source(eventQueue1, al_get_timer_event_source(gameTimer));
    al_register_event_source(eventQueue2, al_get_timer_event_source(gameTimer));
    
    pthread_t thread_npcHandling;
    pthread_t thread_timedAllegroEvents;
    
    pthread_create(&thread_npcHandling, NULL, &Region::handleMapNPCsHelper, (void *)0);
    pthread_create(&thread_timedAllegroEvents, NULL, &Region::timedAllegroEventsHelper, (void *)0);     
}

Region::~Region() {
    al_destroy_event_queue(eventQueue1);
    al_destroy_event_queue(eventQueue2);
    al_destroy_timer(gameTimer);                  
}

void *Region::timedAllegroEvents() {
    while(true) {
        al_wait_for_event(eventQueue1, &event1);
        if(event1.type == ALLEGRO_EVENT_TIMER) {
            for(int i = 0; i < mapRegenTiles.size(); i++) {
                mapRegenTiles[i].Handle();
                if(mapRegenTiles[i].changeDelayReady()) {
                    changeTile(mapRegenTiles[i].ChangeTile(), 1, mapRegenTiles[i].X(), mapRegenTiles[i].Y(), false);
                    mapRegenTiles.erase(mapRegenTiles.begin() + i);                                         
                }    
            }
            for(int i = 0; i < mapRegenNPCs.size(); i++) {
                mapRegenNPCs[i].Handle();
                if(mapRegenNPCs[i].changeDelayReady()) {
                    NPC n;
                    n.newNPC(mapRegenNPCs[i].ChangeNPC());
                    n.setCoordinates(mapRegenNPCs[i].X(), mapRegenNPCs[i].Y());
                    n.setSpawn(mapRegenNPCs[i].X(), mapRegenNPCs[i].Y());
                    int dialoguePos = -1;
                    for(int j = 0; j < NPCdialogueVector.size(); j++) {
                        if(NPCdialogueVector[j].x == mapRegenNPCs[i].X() && NPCdialogueVector[j].y == mapRegenNPCs[i].Y())
                            dialoguePos = j;
                    }
                    n.dialogue = NPCdialogueVector[dialoguePos];
                    n.getAttributes();
                        
                    stringstream npcData;
                    bool hasDialogue = false;
                    hasDialogue = (n.dialogue.messageVector.size() > 0);
                    npcData << (char)hasDialogue << (char)n.Important() << n.X() << "_" << n.Y() << "_" << n.TX() << "_" << n.TY();
                        
                    for(int x = 0; x < MAX_PLAYERS; x++) {
                        if(Players[x].ingame && Players[x].mapNumber == mapID) {
                            Send(P_NPC_SPAWN, Players[x].sock, npcData.str());                
                        }        
                    }
                        
                    mapNPCvector.push_back(n); 
                          
                    mapRegenNPCs.erase(mapRegenNPCs.begin() + i);                                     
                }    
            }
            
            HandleWeather(mapWeatherType, mapWeatherGen);
            
            for(int i = 0; i < mapProjectileVector.size(); i++) {
                mapProjectileVector[i].Handle();
                mapProjectileVector[i].checkForCollision();
                
                if((mapProjectileVector[i].Alpha() <= 0 && mapProjectileVector[i].Velocity() <= 0) || (mapProjectileVector[i].X() < 0 || mapProjectileVector[i].X() > 10240 || mapProjectileVector[i].Y() < 0 || mapProjectileVector[i].Y() > 10240)) {
                    std::stringstream sendData;
                    sendData << i;
                    
                    for(int j = 0; j < MAX_PLAYERS; j++) {
                        if(Players[j].ingame && Players[j].mapNumber == mapID) {
                            Send(P_DEL_PROJECTILE, Players[j].sock, sendData.str());
                        }
                    }
                    
                    mapProjectileVector.erase(mapProjectileVector.begin() + i); 
                }       
            }
        } 
        SDL_Delay(1);
    } 
    
    pthread_exit(NULL);
}
void *Region::handleMapNPCs() {
    while(true) {        
        al_wait_for_event(eventQueue2, &event2);
        if(event2.type == ALLEGRO_EVENT_TIMER) {
            handleNPCs(mapNPCvector, mapProjectileVector);           
            for(int x = 0; x < 320; x++) {
                for(int y = 0; y < 320; y++) {
                    tileCollisionMap[x][y] = false;        
                }        
            }
            
            for(int i = 0; i < MAX_PLAYERS; i++) {
                if(Players[i].ingame && Players[i].mapNumber == mapID) {
                    tileCollisionMap[Players[i].X()][Players[i].Y()] = true;
                }       
            }
          
            for(int i = 0; i < mapNPCvector.size(); i++) {
                tileCollisionMap[mapNPCvector[i].X()][mapNPCvector[i].Y()] = true;      
            }
            
            for(int i = 0; i < mapNPCvector.size(); i++) {
                mapNPCvector[i].checkForCollision(0);        
            }    
        }
        SDL_Delay(1);    
    }
    pthread_exit(NULL);
}


It's a bit long. The server always crashes on "al_wait_for_event". If I comment that line of code out, it will crash on the next line with a reference to another member.
This is going to take a bit of ploughing through

But one question for now is - when do you call the Region::Initialize() function.
I call it after I initialize Allegro. I have an array of Regions, then after Allegro is initialized I loop through the array of Regions and call Initialize() on each one.
May be helpful to tell us what happens when it crashes, does it throw an exception, any messages given, etc. Also, are you using allegro and SDL in this project? Not sure it would be an issue, I'm just curious.
Not sure- the debugger doesn't tell me anything.

Yeah I am- SDL_net for networking and Allegro 5 for the timing and event system(just because I am more familiar with it compared to SDL)
closed account (18hRX9L8)
Exiled wrote:
@usandfriends
It is meant to be- that wouldn't cause a crash regardless. As I said in the original post, it is to show using a value from the class. The two functions are to handle NPCs and to handle timed events. They are supposed to be infinite until the program exits.


If it is infinite, the program will stop there and the system will crash because C++ is line-by-line language, meaning the program executes one line after the other. If it keeps executing the while loop, everything after the loops will never get to see daylight.
Last edited on
I have an array of Regions, then after Allegro is initialized I loop through the array of Regions and call Initialize() on each one.


Never taken any game design classes, but I was in the computer lab today working on an assignment and there was a lab going on in the same classroom. I overheard the TA saying that it is better programming style to not initialise everything in the game over and over as the game is going on because this makes it super slow or something like that. The guy was saying to initialise everything once then access them as needed.
Last edited on
usandfriends:
It crashes- it doesn't have a "blank screen".

Smac89:
That seems pretty irrelevant... I don't initialize it over and over.

I think everyone is forgetting the problem; it is a segfault. It's not a performance problem, it's not a lag problem, it is a segfault.
Topic archived. No new replies allowed.