|
Crash on al_get_time() |
Matias Persson
Member #15,093
May 2013
|
Title says it all. double startTime = al_get_time(); <-- Crash because al_get_time() returns -6.0120304019-18e etc. in my timed logic, though it doesn't really has anything to say as it never reaches this point. Never had this issue before, and this very same program, that hasn't been changed since actually worked yesterday. |
Edgar Reynaldo
Major Reynaldo
May 2007
|
I'm guessing you have a global IntroState object? Is that correct? If so, al_init won't have been called before calling al_get_time and it will crash. That's probably why you're getting the crazy return value for the time. 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 |
Matias Persson
Member #15,093
May 2013
|
No I don't use globals, been trying for days now, still an error. |
Edgar Reynaldo
Major Reynaldo
May 2007
|
Okay, but are you sure you're initializing allegro before you create your IntroState object? Things like that just shouldn't happen unless you're calling allegro functions before allegro_init. My other guess is that you updated allegro and you're using a different version of the allegro dll that is no longer compatible with your current allegro headers. It could cause problems like that. Ie. you updated your headers, but not your dlls. That could cause a runtime crash. Otherwise, you're gonna have to show more code. Show main at least. 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 |
Matias Persson
Member #15,093
May 2013
|
I initialize everything before trying to use any allegro functions. Here's code. 1#include <iostream>
2#include <memory>
3#include <allegro5/allegro.h>
4#include <allegro5/allegro_font.h>
5#include <allegro5/allegro_ttf.h>
6
7#include "GameState.h"
8#include "IntroState.h"
9#include "MenuState.h"
10
11int Initialize(ALLEGRO_DISPLAY *&display, ALLEGRO_EVENT_QUEUE *&event_queue, ALLEGRO_TIMER *&timer);
12void setNextState(int newState);
13void ChangeState();
14int Cleanup(ALLEGRO_DISPLAY *&display, ALLEGRO_EVENT_QUEUE *&event_queue, ALLEGRO_TIMER *&timer);
15
16int stateID = STATE_INTRO;
17int nextState = STATE_NULL;
18std::unique_ptr<CGameState> currentState;
19
20int main() {
21
22 ALLEGRO_DISPLAY *display;
23 ALLEGRO_EVENT_QUEUE *event_queue;
24 ALLEGRO_TIMER *timer;
25 ALLEGRO_EVENT ev;
26
27 Initialize(display, event_queue, timer);
28
29 al_start_timer(timer);
30
31 currentState = std::make_unique<CIntroState>();
32
33 while (stateID != STATE_EXIT) {
34 while (!al_is_event_queue_empty(event_queue)) {
35 al_wait_for_event(event_queue, &ev);
36 //Check input here
37 //Keyboard keyboard;
38 //checkInput(keyboard, ev);
39
40 if (ev.type == ALLEGRO_EVENT_TIMER)
41 {
42 //Do timed logic.
43 currentState->TimedLogic(nextState);
44 }
45 else if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
46 //Set to exit state, if user closes the program.
47 setNextState(STATE_EXIT);
48 }
49 //Do untimed logic.
50 currentState->UntimedLogic();
51 }
52
53 currentState->Render();
54
55 //Change state if needed
56 ChangeState();
57
58 al_rest(0.001);
59 }
60
61 Cleanup(display, event_queue, timer);
62}
63
64int Initialize(ALLEGRO_DISPLAY *&display, ALLEGRO_EVENT_QUEUE *&event_queue, ALLEGRO_TIMER *&timer) {
65 if (!al_init()) {
66 return -1;
67 }
68
69 display = al_create_display(640, 480);
70 if (!display) {
71 al_destroy_display(display);
72 return -1;
73 }
74
75 event_queue = al_create_event_queue();
76 if (!event_queue) {
77 al_destroy_event_queue(event_queue);
78 return -1;
79 }
80
81 timer = al_create_timer(1.0 / 60.0);
82 if (!timer) {
83 al_destroy_timer(timer);
84 return -1;
85 }
86
87 al_install_keyboard();
88 al_install_mouse();
89 al_init_font_addon();
90 al_init_ttf_addon();
91
92 al_register_event_source(event_queue, al_get_display_event_source(display));
93 al_register_event_source(event_queue, al_get_timer_event_source(timer));
94 al_register_event_source(event_queue, al_get_keyboard_event_source());
95 al_register_event_source(event_queue, al_get_mouse_event_source());
96
97 return 1;
98}
99
100void setNextState(int newState) {
101 if (nextState != STATE_EXIT)
102 nextState = newState;
103}
104
105void ChangeState() {
106 if (nextState != STATE_NULL) {
107 switch (nextState) {
108 case STATE_INTRO:
109 currentState = std::make_unique<CIntroState>();
110 break;
111 case STATE_MENU:
112 currentState = std::make_unique<CMenuState>();
113 break;
114 case STATE_PLAY:
115 break;
116 }
117
118 stateID = nextState;
119
120 nextState = STATE_NULL;
121 }
122}
123
124int Cleanup(ALLEGRO_DISPLAY *&display, ALLEGRO_EVENT_QUEUE *&event_queue, ALLEGRO_TIMER *&timer) {
125 al_destroy_display(display);
126 al_destroy_timer(timer);
127 al_destroy_event_queue(event_queue);
128 return 0;
129}
GameState.h 1#pragma once
2
3//#include "Keyboard.h"
4
5enum GameStates {STATE_NULL, STATE_INTRO, STATE_MENU, STATE_PLAY, STATE_EXIT};
6
7class CGameState
8{
9public:
10 CGameState();
11 virtual ~CGameState() = 0;
12
13 virtual void TimedLogic(int &nextState) = 0;
14 virtual void UntimedLogic() = 0;
15 virtual void Render() = 0;
16};
IntroState.h 1#pragma once
2
3#include "GameState.h"
4
5#include <iostream>
6#include <allegro5/allegro.h>
7#include <allegro5/allegro_font.h>
8#include <allegro5/allegro_ttf.h>
9
10class CIntroState :
11 public CGameState
12{
13public:
14 CIntroState();
15 ~CIntroState();
16
17 void TimedLogic(int &nextState);
18 void UntimedLogic();
19 void Render();
20
21private:
22 double startTime;
23 ALLEGRO_FONT *arial;
24};
|
Peter Hull
Member #1,136
March 2001
|
Seems like you've thought of everything! Questions:
As an aside, where you have display = al_create_display(640, 480); if (!display) { al_destroy_display(display); return -1; } this doesn't make sense; if al_create_display returns NULL, it's failed and there is nothing to call al_destroy_display on.
|
Bruce Pascoe
Member #15,931
April 2015
|
If al_get_time() is returning insane values, that's usually because you've called it before initializing Allegro. That doesn't appear to be the case here though, so it's definitely weird. I see global variables though.
|
SiegeLord
Member #7,827
October 2006
|
Edgar Reynaldo said: My other guess is that you updated allegro and you're using a different version of the allegro dll that is no longer compatible with your current allegro headers. It could cause problems like that. Ie. you updated your headers, but not your dlls. That could cause a runtime crash. That's a possibility. You check for al_init succeeding, but you don't check for Initialize succeeding. al_init might fail, and and you might proceed anyway and get all sorts of crashes. Weird that al_start_timer doesn't crash though . "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Edgar Reynaldo
Major Reynaldo
May 2007
|
From my experience, when al_init fails, it's usually because of a version mismatch between the headers compiled against and the dll in use. Allegro does a version check on start up inside al_init that will fail if the runtime is different from the headers used. 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 |
Matias Persson
Member #15,093
May 2013
|
Sorry for the late reply, been busy lately. Peter Hull: 1#include "IntroState.h"
2
3CIntroState::CIntroState()
4{
5 std::cout << "Entered Intro State" << std::endl;
6 startTime = al_get_time();
7 arial = al_load_font("arial.ttf", 12, 0);
8 if (!arial) {
9 al_destroy_font(arial);
10 exit(-1);
11 }
12}
13
14CIntroState::~CIntroState() {
15 std::cout << "Leaving Intro State" << std::endl;
16}
17
18void CIntroState::TimedLogic(int &nextState) {
19 if (al_get_time() - startTime >= 5.0) {
20 nextState = STATE_MENU;
21 }
22}
On your aside text, do you propose I should say: if(!display = al_create_display(640,480)) { return 0; } instead? Still having issues with this, very weird.. As I said, it works on my desktop computer. |
Bruce Pascoe
Member #15,931
April 2015
|
Looking at that code and what you posted above, you're definitely calling al_init() before al_get_time(), so not sure why you're getting insane values. The only thing I can think of is that initialization is failing behind your back (as mentioned above, you aren't checking the return value of Initialize() ).
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
al_init is most likely failing for some reason or another. Check the return value. :/ 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 |
Neil Roy
Member #2,229
April 2002
|
if(!display = al_create_display(640,480)) { return 0; } I would just change your original code you posted for this to... if(display == NULL) { return -1; } You're also making the same mistake with your font loading... arial = al_load_font("arial.ttf", 12, 0); if (!arial) { al_destroy_font(arial); exit(-1); } You're trying to destroy the arial font, but that is only needed if you successfully loading it in the first place. If loading fails, than there is nothing to destroy, no need to call that. Just use arial = al_load_font("arial.ttf", 12, 0); if (arial == NULL) { exit(-1); } As for your main problem, according to the online docs (https://www.allegro.cc/manual/5/al_get_time): "The return value is undefined if Allegro is uninitialised." Looking at your code, I see a problem right away... what is this... int Initialize(ALLEGRO_DISPLAY *&display, ALLEGRO_EVENT_QUEUE *&event_queue, ALLEGRO_TIMER *&timer); You have *&display? ? You only need &display in C++ or *display but not both. So the problem is that Allegro is not being initialized properly. So your function prototype should be... int Initialize(ALLEGRO_DISPLAY &display, ALLEGRO_EVENT_QUEUE &event_queue, ALLEGRO_TIMER &timer); and in main() you should have... ALLEGRO_DISPLAY *display; ALLEGRO_EVENT_QUEUE *event_queue; ALLEGRO_TIMER *timer; ALLEGRO_EVENT ev; Initialize(display, event_queue, timer);
--- |
Bruce Pascoe
Member #15,931
April 2015
|
No, *& is correct - he's passing the ALLEGRO_DISPLAY* by reference. I'm pretty sure ALLEGRO_DISPLAY& won't compile because that's an opaque type (i.e. Allegro doesn't expose the actual struct contents so the compiler doesn't know how large it is).
|
Neil Roy
Member #2,229
April 2002
|
He's passing a pointer. So the function should take a pointer or a reference, but not both. Never used both together before and honestly, I am surprised it compiled like that. --- |
Bruce Pascoe
Member #15,931
April 2015
|
He's passing a reference to the pointer, that's correct. al_create_display() returns ALLEGRO_DISPLAY*, so you have to have a reference to the pointer type if you want to store it. It might clarify things to say that, if this were C where pass-by-reference isn't allowed, for Initialize() to work the way it's set up now, it would have to take an ALLEGRO_DISPLAY** (a pointer to the pointer).
|
Peter Hull
Member #1,136
March 2001
|
Matias Persson said: As I said, it works on my desktop computer. Dunno, did you say that? Do you mean the exact same binary copied from one computer to the other works on one and not the other? Or are you compiling the same source code on each one? As has been mentioned al_init failing (somehow) seems likely - another possibility is that al_get_time is OK but the stored value (CIntroState::startTime) is being corrupted subsequently. If you get your debugger on the place where it's being set, is it always garbage?
|
Matias Persson
Member #15,093
May 2013
|
Exact same source code, not binary. |
|