|
What do these errors mean? |
North~
Member #12,192
August 2010
|
#0 777B2086 ntdll!RtlUnhandledExceptionFilter() (C:\Windows\system32\ntdll.dll:??) Something to do with not having enough memory right? Or compatibility or... something? -------------------------------------------------- If this is possible if you don't correctly initialize memory, it should be a priority of the highest order. |
Audric
Member #907
January 2001
|
I'd say a bug in your code, an error on how you handle memory. |
Edgar Reynaldo
Major Reynaldo
May 2007
|
Those aren't errors, that is a backtrace of the current function stack. Are there really only 6 frames there? If so, it looks like you didn't compile with debugging symbols, so your backtrace isn't very useful. What error did you get? SIGSEGV? From frame 3 it looks like you were trying to free memory. Did you call delete twice on the same memory or use the wrong kind of delete on memory allocated with new? My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
torhu
Member #2,727
September 2002
|
If it's free() that crashes, you might have given it an invalid pointer, or you are trying to free the same memory twice. EDIT: wow, 3 answers at almost the exact same time |
Arthur Kalliokoski
Second in Command
February 2005
|
If you alter a pointer that's been malloc()'ed with pointer arithmetic it'll crash. They all watch too much MSNBC... they get ideas. |
North~
Member #12,192
August 2010
|
Quick answers indeed xD I'll re-check all my pointers. EDIT: and no, I didn't use wrong pointer de-allocation. only new and delete. -------------------------------------------------- If this is possible if you don't correctly initialize memory, it should be a priority of the highest order. |
Edgar Reynaldo
Major Reynaldo
May 2007
|
If you look at your other thread I pointed out there that you are mixing new [] with delete. That might be what caused it. Or it might be that your EventQueue class deletes Events, and you might also be delete [] 'ing the same array of Events. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
torhu
Member #2,727
September 2002
|
delete calls free, it can create the same issues. |
North~
Member #12,192
August 2010
|
Fixed what you said (I think) but I'm still getting the same errors. It's coming from a for loop (as I pinpointed it down) here: 1for (int i=0;i<10;i++)
2 {
3 enemywave1_paths[i].set_path(enemywave1_ships[i].get_speed(),550,y,20,1);
4 printf("Vector Path %d set.\n",i);
5 y-=70;
6 enemywave1_ships[i].set_path(&enemywave1_paths[i]);
7 printf("Ship Path %d set.\n",i);
8 waves[0].AddEnemy(enemywave1_ships[i]);
9 }
10
11
12
13
14//Allocated as such
15enemywave1_ships = new PawnShip[10]();
16 if (enemywave1_ships)
17 printf("Ships allocated.\n");
18
19 enemywave1_paths = new WaveVector[10]();
20 if (enemywave1_paths)
21 printf("Vectors allocated.\n");
22
23
24
25//and delete[]d as such
26delete[] waves;
27delete[] enemywave1_ships;
28delete[] enemywave1_paths;
But it goes through the loop about 2-5 times, THEN it says that it's having trouble. That... doesn't make any sense to me, which is why I thought it had something to do with a memory error (besides just syntax-based issues) delete is just free but it calls the destructor right? -------------------------------------------------- If this is possible if you don't correctly initialize memory, it should be a priority of the highest order. |
Edgar Reynaldo
Major Reynaldo
May 2007
|
North~ said: delete is just free but it calls the destructor right? Yes, that's true. Your best bet is to compile with debugging symbols so you can get a real backtrace. If using MinGW, that means adding -g to your compilation command. If using Code::Blocks, go to Menu->Project->Build Options->Debug configuration->Compiler Settings and check 'Produce debugging symbols'. MSVC should have a similar setting somewhere as well. If you're going to use delete [] waves, then you need to make sure your EventQueue class does not delete those events. Duplicate deletion will usually crash. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
North~
Member #12,192
August 2010
|
It's already doing that (I'm using the debug target |3) EDIT:: Did a bit more inspecting and it seems to be failing at waves[0].AddEnemy(enemywave1_ships[i]); the second time (as in it's not even getting to the adding the event to the queue yet). Always. I still don't know what the problem is... -------------------------------------------------- If this is possible if you don't correctly initialize memory, it should be a priority of the highest order. |
Edgar Reynaldo
Major Reynaldo
May 2007
|
Post your latest Event.cpp and Event.h then. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
North~
Member #12,192
August 2010
|
Event.h 1#ifndef SA_EVENT_H
2#define SA_EVENT_H
3
4enum EVENT_STATE
5{
6 EVENT_NOT_YET = 0,
7 EVENT_TRIGGERED = 1
8};
9
10class Event
11{
12 public :
13 Event(){}
14 virtual ~Event() {}
15
16 virtual EVENT_STATE Update()=0;
17 virtual void Perform()=0;
18};
19
20class NewEnemyWaveEvent : public Event
21{
22 private :
23 std::vector<EnemyShip> new_enemies;
24
25 public :
26 NewEnemyWaveEvent() : new_enemies() {}
27 EVENT_STATE Update();
28 void Perform();
29 void AddEnemy(EnemyShip e);
30};
31
32class EnemyShootEvent : public Event
33{
34 private:
35 EnemyShip* c;
36 public:
37 EnemyShootEvent() : c() {}
38 int assign(EnemyShip* b);
39 EVENT_STATE Update();
40 void Perform();
41};
42
43#endif
44// SA_EVENT_H
Event.cpp 1#include <vector>
2#include <stdio.h>
3#include "../SME_Engine/Projectile.h"
4#include "Vector.h"
5#include "Ship.h"
6#include "Event.h"
7#include "EnemyList.h"
8
9extern EnemyList eList;
10
11EVENT_STATE NewEnemyWaveEvent::Update()
12{
13 if (eList.size() == 0)
14 {
15 return EVENT_TRIGGERED;
16 }
17 return EVENT_NOT_YET;
18}
19
20void NewEnemyWaveEvent::Perform()
21{
22 for (unsigned int i = 0 ; i < new_enemies.size() ; i++)
23 {
24 eList.AddEnemy(new_enemies[i]);
25 }
26 printf("Enemy List Size: %d\n",eList.size());
27}
28
29void NewEnemyWaveEvent::AddEnemy(EnemyShip e)
30{
31 new_enemies.push_back(e);
32}
33
34int EnemyShootEvent::assign(EnemyShip* b)
35{
36 if (b->gety() > 0 && b->gety() < SCREEN_H - 60)
37 { c = b; return 1; }
38 else { return 0;}
39}
40
41EVENT_STATE EnemyShootEvent::Update()
42{
43 if (c->isFiring()) { return EVENT_TRIGGERED; }
44
45 return EVENT_NOT_YET;
46}
47
48void EnemyShootEvent::Perform()
49{
50 c->fire_bullet(5);
51}
Tried changing everything to vectors to eliminate the delete[] problem (didn't work) Also, The "Ship" files for the EnemyShip that seems to be having a problem being added to the event. 1#ifndef SA_SHIPS_H
2#define SA_SHIPS_H
3
4class EnemyShip;
5
6class Ship
7{
8 private:
9 std::vector<Projectile> bullet;
10 std::vector<Projectile> missile;
11 int x,y;
12 int speed;
13 int hp;
14 int missiles;
15 public:
16 Ship(int x, int y);
17 ~Ship(){}
18 void display_HUD(BITMAP* display);
19 void move(BITMAP* display);
20 void bullet_check(BITMAP* display);
21 bool hit_by_bullet(EnemyShip* e);
22
23};
24
25class EnemyShip //never declared. declare a TYPE of enemyship (PawnShip, ModerateShip, MotherShip, etc.)
26{
27 protected:
28 std::vector<Projectile> bullet;
29 WaveVector* path;
30 BITMAP* enemy_ship_bmp;
31 int prob_numerator, prob_denominator; // chances of firing ( get higher as a better ship )
32 float x,y;
33 int hp,speed;
34 bool active;
35 bool firing;
36 friend class Ship;
37 public:
38 int get_speed() { return speed; }
39 EnemyShip();
40 ~EnemyShip() { destroy_bitmap(enemy_ship_bmp); }
41 int getx() { return x; }
42 int gety() { return y; }
43 bool get_active() { return active; }
44 bool isFiring() { return firing; }
45 int get_numer() { return prob_numerator; }
46 int get_denom() { return prob_denominator; }
47
48 void move(BITMAP* display);
49 void fire_bullet(int speed);
50 void check_bullet(BITMAP* display);
51 bool fire_bullet_random();
52 void set_path(WaveVector* vec);
53};
54
55class PawnShip : public EnemyShip
56{
57 public:
58 PawnShip();
59 ~PawnShip(){}
60};
61
62class ModerateShip : public EnemyShip
63{
64 public:
65 ModerateShip();
66 ~ModerateShip(){}
67};
68
69class MotherShip : public EnemyShip
70{
71 public:
72 MotherShip();
73 ~MotherShip(){}
74};
75#endif //SA_SHIPS_H
76
77
78
79
80#include <ctime>
81#include "../SME_Engine/Projectile.h"
82#include <allegro.h>
83#include "Vector.h"
84#include "Ship.h"
85
86BITMAP* bmpShipSprite, *bmpBullet, *bmpEnemyBullet;
87clock_t currentTime_bullet = std::clock(), placeHolder_bullet = std::clock();
88
89Ship::Ship(int x, int y)
90{
91 this->x = x;
92 this->y = y;
93 speed = 4;
94 hp = 3;
95 missiles = 3;
96 bmpShipSprite = load_bitmap("data/practice/ship.bmp",NULL);
97 bmpBullet = load_bitmap("data/practice/shot.bmp",NULL);
98
99 bullet.resize(15);
100 for (int i=0;i<15;i++)
101 {
102 bullet[i].setBitmap(bmpBullet);
103 bullet[i].reset(x+bmpShipSprite->w,y+(bmpShipSprite->w/2) - bmpBullet->h);
104 }
105
106 missile.resize(3);
107}
108
109void Ship::move(BITMAP* display)
110{
111 if (key[KEY_UP] && y > 5)
112 y -= speed;
113 if (key[KEY_DOWN] && y + bmpShipSprite->h < SCREEN_H)
114 y += speed;
115
116 masked_blit(bmpShipSprite,display,0,0,x,y,bmpShipSprite->w,bmpShipSprite->h);
117}
118
119void Ship::bullet_check(BITMAP* display)
120{
121 currentTime_bullet = std::clock();
122
123 for (int i=0;i<15;i++)
124 {
125 bullet[i].move(display,x+bmpShipSprite->w,(y+bmpShipSprite->h)/2);
126
127 if (!bullet[i].getActive()) { bullet[i].reset(x+bmpShipSprite->w,y+(bmpShipSprite->w/2) - bmpBullet->h); } //reset bullets since we're moving and shooting is continuous.
128 }
129
130 if (key[KEY_SPACE] && currentTime_bullet > placeHolder_bullet + 200)
131 {
132 int j=0;
133 bool avaliable = false;
134 for(int i=0;i<15;i++)
135 {
136 if (!bullet[i].getActive())
137 {
138 avaliable = true;
139 j = i;
140 break;
141 }
142 }
143 bullet[j].fire(5);
144
145 placeHolder_bullet = std::clock();
146 }
147 if (key[KEY_LSHIFT])
148 if(missiles > 0) { }
149}
150///*//////////////////////////////////////////////////////////////////////////////////////
151
152EnemyShip::EnemyShip()
153{
154 x = 0; y = 0;
155 active = true;
156}
157
158void EnemyShip::move(BITMAP* display)
159{
160 if (active)
161 {
162
163 x = path->coordx[path->coord_index];
164 y = path->coordy[path->coord_index];
165
166 if (path->coord_index >= path->get_max() - 1)
167 {
168 active = false;
169 }
170
171 draw_sprite(display,enemy_ship_bmp,x,y);
172
173 path->coord_index++;
174 }
175}
176
177void EnemyShip::fire_bullet(int speed)
178{
179 int j=0;
180 bool avaliable = false;
181 for(unsigned int i=0;i<bullet.size();i++)
182 {
183 if (!bullet[i].getActive())
184 {
185 avaliable = true;
186 j = i;
187 bullet[j].setX(x);
188 bullet[j].setY(y + (enemy_ship_bmp->h / 2) - bullet[j].getH());
189 bullet[j].fire(-speed);
190 break;
191 }
192 }
193
194 firing = false;
195}
196
197void EnemyShip::check_bullet(BITMAP* display)
198{
199 for(unsigned int o=0;o<bullet.size();o++)
200 bullet[o].move(display,x, (y + (enemy_ship_bmp->h/2) - bullet[o].getH()));
201}
202
203bool EnemyShip::fire_bullet_random() //check if the probability of shooting for an enemy has returned a true value
204{
205 srand(time(NULL));
206 int secondrand = rand() % 100000;
207 srand(time(NULL) + secondrand);
208
209 if ( (rand() % prob_denominator - prob_numerator) == (prob_denominator + prob_numerator)/2 ) { firing = true; return true; }
210 else { firing = false; return false; }
211}
212
213void EnemyShip::set_path(WaveVector* vec)
214{
215 path = vec;
216}
217
218PawnShip::PawnShip() :
219 EnemyShip()
220{
221 bullet.resize(3);
222 for (unsigned int i=0;i<bullet.size();i++)
223 {
224 bullet[i].setBitmap(bmpEnemyBullet);
225 }
226 enemy_ship_bmp = load_bitmap("data/practice/enemy.bmp",NULL);
227 if (!enemy_ship_bmp)
228 {
229 allegro_message("Failed to load Enemy Ship bitmap.");
230 exit(1);
231 }
232 hp = 1;
233 speed = 2;
234 prob_numerator = 1;
235 prob_denominator = 120;
236}
-------------------------------------------------- If this is possible if you don't correctly initialize memory, it should be a priority of the highest order. |
Edgar Reynaldo
Major Reynaldo
May 2007
|
North~ said:
class NewEnemyWaveEvent : public Event { private :
Like I said before in your other thread, you can't add classes derived from EnemyShip to your vector this way. Your vector has to be of EnemyShip*'s, so that when you call AddEnemy(EnemyShip* e) they can be cast by the compiler to an EnemyShip* (the base class). You may not want to make a separate class for EnemyShootEvent. The EventQueue as you have it now handles events in a linear fashion. You might want more than one enemy ship to be able to attack per update and so you would have to modify your EventQueue to handle this. I think it would just be easier to have a list of Enemy projectiles that are active and work with that instead. North~ said: Tried changing everything to vectors to eliminate the delete[] problem (didn't work) If you use vectors instead then you will have to implement the assignment operator and the copy constructor for each class that will go into a vector if the compiler generated versions don't perform a deep copy (allocate all memory and copy it). (Of course this only applies if your vector is of objects and not object pointers). If you would look more closely at the backtrace of when the program crashes, you can see which frame and line is causing the crash. With delete that usually means deleting something twice. Your EnemyShip destructor still isn't virtual. Base class destructors should always be virtual. And since you destroy a bitmap in the EnemyShip destructor, then that means you have to load/create a bitmap for each EnemyShip (and its derived classes). It would be easier to load a single bitmap for each type of ship once and then make EnemyShip just use a pointer to it. Logic functions like EnemyShip::move should not draw anything, only move it. Keep logic and drawing as separate as you can. Like I said before, a constructor should initialize every data member of the class using an initialization list. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
North~
Member #12,192
August 2010
|
I see... Thank you very much for the information, (I need to listen to and analyze what you say more often xD) and yes I do want multiple ships to be able to fire at the same time. The errors did seem to change when I changed PawnShip to EnemyShip. Derived classes are the only ones that need to initialize their private members with the colon operator right? EDIT::Now it does something familiar, the enemies blit etc., but when they start coming out, the EnemyShootEvent (haven't changed it yet) doesn't seem to work or inits about 10 events at the same time (whoa, what) and there's an odd static-like fuzz in a vertical line appearing until they all get on screen, then it disappears. -------------------------------------------------- If this is possible if you don't correctly initialize memory, it should be a priority of the highest order. |
Edgar Reynaldo
Major Reynaldo
May 2007
|
North~ said: Derived classes are the only ones that need to initialize their private members with the colon operator right? As a matter of course, all classes should initialize all their members (and base classes) in their constructors. The alternative is that each data member is initialized using it's default constructor. Which in the case of built in types, they are not initialized at all in the default constructor. Want to read the old values of a MB of memory? Declare char* mem = new char[1024*1024]; and print out the values of mem in a for loop without initializing them. You never know what you might find! Regarding your Edit, not sure what is going on there. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
North~
Member #12,192
August 2010
|
Interesting. And it's happened before. I fixed it by erasing a delete which... I think actually caused a memory leak but it solved the problem which makes no sense whatsoever. But... I'll look more into it. -------------------------------------------------- If this is possible if you don't correctly initialize memory, it should be a priority of the highest order. |
Audric
Member #907
January 2001
|
There's one technique... After you free() or delete something, you can take the habit of systematically set it to NULL. I'm not 100% sure it's a good habit while learning, because it silently fixes some problems in your code, you don't learn the hard way. |
Timorg
Member #2,028
March 2002
|
Edgar Reynaldo said: Declare char* mem = new char[1024*1024]; and print out the values of mem in a for loop without initializing them. You never know what you might find! Well you might just find your name projected onto the ground with ninja rabbits running around on it. Always initialize your memory ____________________________________________________________________________________________ |
North~
Member #12,192
August 2010
|
Oh wow. I didn't even know that was possible xD Honestly... that's amazing |3 -------------------------------------------------- If this is possible if you don't correctly initialize memory, it should be a priority of the highest order. |
|