Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » What do these errors mean?

This thread is locked; no one can reply to it. rss feed Print
What do these errors mean?
North~
Member #12,192
August 2010

#0 777B2086 ntdll!RtlUnhandledExceptionFilter() (C:\Windows\system32\ntdll.dll:??)
#1 777B18C3 ntdll!RtlFreeThreadActivationContextStack() (C:\Windows\system32\ntdll.dll:??)
#2 763A7A7E KERNEL32!HeapLock() (C:\Windows\system32\kernel32.dll:??)
#3 7730A097 msvcrt!free() (C:\Windows\system32\msvcrt.dll:??)
#4 00000000 0x00ab0000 in ??() (??:??)
#5 00000000 0x00000000 in ??() (??:??)

Something to do with not having enough memory right? Or compatibility or... something?

--------------------------------------------------
http://blog.wolfire.com/2009/04/always-initialize-your-memory/

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.
You free the same memory address twice, or free something you didn't allocate...
Double-check your pointers.
I think I knew one other method/mistake that thrashes the memory used by the malloc system (so that further malloc/free would crash hard) but I can't recall it ATM.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

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?

torhu
Member #2,727
September 2002
avatar

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 :P

Arthur Kalliokoski
Second in Command
February 2005
avatar

If you alter a pointer that's been malloc()'ed with pointer arithmetic it'll crash.
If you set pointers within a malloc()'ed block, then use realloc(), it may invalidate those pointers.

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.

--------------------------------------------------
http://blog.wolfire.com/2009/04/always-initialize-your-memory/

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
avatar

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.

torhu
Member #2,727
September 2002
avatar

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:

#SelectExpand
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?

--------------------------------------------------
http://blog.wolfire.com/2009/04/always-initialize-your-memory/

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
avatar

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.

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...

--------------------------------------------------
http://blog.wolfire.com/2009/04/always-initialize-your-memory/

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
avatar

North~
Member #12,192
August 2010

Event.h

#SelectExpand
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

#SelectExpand
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.

#SelectExpand
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}

--------------------------------------------------
http://blog.wolfire.com/2009/04/always-initialize-your-memory/

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
avatar

North~ said:

class NewEnemyWaveEvent : public Event
{
    private :
std::vector<EnemyShip> new_enemies;

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.

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.

--------------------------------------------------
http://blog.wolfire.com/2009/04/always-initialize-your-memory/

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
avatar

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.

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.

--------------------------------------------------
http://blog.wolfire.com/2009/04/always-initialize-your-memory/

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.
This way, if you accidentally free() or delete it again later, the second operation has no effect at all (free(null) and delete null do nothing, it's guaranteed by the standard). It's also easier to catch a problem in one of your "if (thing!=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

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. :D

Always initialize your memory
{"name":"1.jpg","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/c\/3c6e6d81590528c8834c52bd7064438d.jpg","w":1280,"h":676,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/c\/3c6e6d81590528c8834c52bd7064438d"}1.jpg

____________________________________________________________________________________________
"c is much better than c++ if you don't need OOP simply because it's smaller and requires less load time." - alethiophile
OMG my sides are hurting from laughing so hard... :D

North~
Member #12,192
August 2010

Oh wow. I didn't even know that was possible xD

Honestly... that's amazing |3

--------------------------------------------------
http://blog.wolfire.com/2009/04/always-initialize-your-memory/

If this is possible if you don't correctly initialize memory, it should be a priority of the highest order.

Go to: