So, I'm using allegro game programming library. Before I move on to bigger and better things I wnat to get a handle on pointers. Specifically with things like structs, linked lists and maybe binary trees in the future. I posted a program that uses a linked list to keep tracks of a variable number of objects on the screen. GDB tells me it fails in the main

also, the new style of posting is kinda buggy, for example I can move the cursor past the program code.

gdb:

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000006
[Switching to process 84322]
0x0000000100001a60 in _al_mangled_main ()
(gdb) bt
#0  0x0000000100001a60 in _al_mangled_main ()
#1  0x000000010006c697 in call_user_main [inlined] () at /Users/me/Desktop/stuff/allegro/src/macosx/osx_app_delegate.m:214
#2  0x000000010006c697 in +[AllegroAppDelegate app_main:] (self=<value temporarily unavailable, due to optimizations>, _cmd=<value temporarily unavailable, due to optimizations>, arg=<value temporarily unavailable, due to optimizations>) at /Users/me/Desktop/stuff/allegro/src/macosx/osx_app_delegate.m:225
#3  0x00007fff8029a114 in __NSThread__main__ ()
#4  0x00007fff8210afd6 in _pthread_start ()
#5  0x00007fff8210ae89 in thread_start ()

code:

#include <cstdlib>
#include <stdlib.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_primitives.h>

const float FPS = 60;
const int SCREEN_W = 640;
const int SCREEN_H = 480;
const int BOUNCER_SIZE = 32;
float startx = 570;
float starty = 200;
int max = 11;
float dx = -10;

struct circle 
{
    float x;
    float y;
    float dy;
    struct circle *c;
} *top;
struct circle* deepcopy(struct circle*& a);
void add(struct circle*& a);
void pop(struct circle*& a);
void renew(struct circle*& a);
void push(struct circle*& a, struct circle* b);
void move(struct circle*& a);
int count(struct circle* a);

int count(struct circle* a)
{
    int c = 0;
    for(struct circle* b = a;b!=NULL;b=b->c)
    {
        c++;
    }
    return c;
}
struct circle* deepcopy(struct circle*& a)
{
    struct circle* b = new circle;
    b->x=a->x;
    b->y=a->y;
    b->dy=a->dy;
    return b;
}
void add(struct circle*& a)
{
    if(a!=NULL)
    {
    struct circle *nnew;
    nnew->x=startx;
    nnew->y=starty;
    nnew->dy= (float)((rand() % (2*max)) - max);
    nnew->c = a;
    a = nnew;
    }
    else {
        a = new struct circle;
        a->x=startx;
        a->y=starty;
        a->dy= (float)((rand() % (2*max)) - max);
    }

}
void pop(struct circle*& a)
{
    struct circle *c = a;
    a=a->c;
    free(c);
}
void renew(struct circle*& a)
{
    struct circle *nnew;
    while(a!=NULL)
    {
        if(!((a->x<=0)||(a->x>=SCREEN_W)||(a->y<=0)||(a->y>=SCREEN_H)))
        {
            struct circle *b = deepcopy(a);
            push(nnew,b);
        }
        pop(a);
        a=a->c;
    }
    a = nnew;
}
void push(struct circle*& a, struct circle* b)
{
    b->c=a;
    a = b;
}
void move(struct circle*& a)
{
    struct circle *b = a;
    while(b!=NULL)
    {
        b->x+=dx;
        b->y+=b->dy;
        b=b->c;
    }
}
int main(int argc, char **argv)
{
   top = NULL;
   ALLEGRO_DISPLAY *display = NULL;
   ALLEGRO_EVENT_QUEUE *event_queue = NULL;
   ALLEGRO_TIMER *timer = NULL;
   ALLEGRO_BITMAP *bouncer = NULL;
   float bouncer_x = SCREEN_W / 2.0 - BOUNCER_SIZE / 2.0;
   float bouncer_y = SCREEN_H / 2.0 - BOUNCER_SIZE / 2.0;
   bool redraw = true;

   if(!al_init()) {
      fprintf(stderr, "failed to initialize allegro!\n");
      return -1;
   }

   if(!al_install_mouse()) {
      fprintf(stderr, "failed to initialize the mouse!\n");
      return -2;
   }

   timer = al_create_timer(1.0 / FPS);
   if(!timer) {
      fprintf(stderr, "failed to create timer!\n");
      return -3;
   }

   display = al_create_display(SCREEN_W, SCREEN_H);
   if(!display) {
      fprintf(stderr, "failed to create display!\n");
      al_destroy_timer(timer);
      return -4;
   }

   bouncer = al_create_bitmap(BOUNCER_SIZE, BOUNCER_SIZE);
   if(!bouncer) {
      fprintf(stderr, "failed to create bouncer bitmap!\n");
      al_destroy_display(display);
      al_destroy_timer(timer);
      return -5;
   }
   if(!al_init_primitives_addon())
   {
       fprintf(stderr,"primitives didn't load\n");
       return -6;
   }
   al_set_target_bitmap(bouncer);
   al_clear_to_color(al_map_rgb(255, 0, 255));
   al_draw_circle((float)BOUNCER_SIZE/2,(float)BOUNCER_SIZE/2,(float)BOUNCER_SIZE/3,al_map_rgb(255,255,255),3);
   al_set_target_bitmap(al_get_backbuffer(display));
   event_queue = al_create_event_queue();
   if(!event_queue) {
      fprintf(stderr, "failed to create event_queue!\n");
      al_destroy_bitmap(bouncer);
      al_destroy_display(display);
      al_destroy_timer(timer);
      return -1;
   }

   al_register_event_source(event_queue, al_get_display_event_source(display));
   al_register_event_source(event_queue, al_get_timer_event_source(timer));
   al_register_event_source(event_queue, al_get_mouse_event_source());
   al_clear_to_color(al_map_rgb(0,0,0));
   al_flip_display();
   al_start_timer(timer);

   while(1)
   {
      ALLEGRO_EVENT ev;
      al_wait_for_event(event_queue, &ev);

      if(ev.type == ALLEGRO_EVENT_TIMER) {
         redraw = true;
      }
      else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
         break;
      }
      else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES ||
              ev.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY) {

         bouncer_x = ev.mouse.x;
         bouncer_y = ev.mouse.y;
      }
      else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
          break;
      }
      if(redraw && al_is_event_queue_empty(event_queue)) {
         redraw = false;
         al_clear_to_color(al_map_rgb(0,0,0));
         //al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0);
         if(count(top)<=max)
         {
             add(top);
         }
         for(struct circle *a=top;a!=NULL;a=a->c)
         {
             al_draw_bitmap(bouncer,a->x,a->y,0);
         }
         move(top);
         renew(top);
         al_flip_display();
      }
   }
   al_destroy_bitmap(bouncer);
   al_destroy_timer(timer);
   al_destroy_display(display);
   al_destroy_event_queue(event_queue);

   return 0;
}

In c++ the best way to avoid pointer problems is not to use pointers, or use smart pointers. Instead of writing your own linked list algorithms use std::vector (arrays) opr std::list (linked list) and those classes will handle all the pointers.

Fair enough, I'll eventually rewrite this using C++ built in features, especially vector, but the whole point of this code is to LEARN how the use pointers correctly. Which for me is really important

OK. I got it to compile and work. Its possible I still have a memory leak in there somewhere but nothing serious enough to cause the program to crash.

Also sorry for the double post

fixed code:

#include <cstdlib>
#include <stdlib.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_primitives.h>

const float FPS = 60;
const int SCREEN_W = 640;
const int SCREEN_H = 480;
const int BOUNCER_SIZE = 32;
float startx = 570;
float starty = 200;
int max = 11;
float dx = -10;

struct circle 
{
    float x;
    float y;
    float dy;
    struct circle *c;
} *top;
void deepcopy(struct circle*& a, struct circle*& b);
void add(struct circle*& a);
void pop(struct circle*& a);
void renew(struct circle*& a);
void push(struct circle*& a, struct circle* b);
void move(struct circle*& a);
int count(struct circle* a);

int count(struct circle* a)
{
    int c = 0;
    for(struct circle* b = a;b!=0;b=b->c)
    {
        c++;
    }
    return c;
}
void deepcopy(struct circle*& a, struct circle*& b)
{
    b->x=a->x;
    b->y=a->y;
    b->dy=a->dy;
}
void add(struct circle*& a)
{
    if(a!=0)
    {
    struct circle* nnew = new circle;
    nnew->x=startx;
    nnew->y=starty;
    nnew->dy= (float)((rand() % (2*max)) - max);
    nnew->c = a;
    a = nnew;
    }
    else {
        a = new circle;
        if(a==0)
        {
            throw "In add, new operator failed";
        }
        a->x=startx;
        a->y=starty;
        a->dy=(float)((rand() % (2*max)) - max);
        a->c=0;
    }

}
void pop(struct circle*& a)
{
    struct circle *c = a;
    a=a->c;
    free(c);
}
void renew(struct circle*& a)
{
    struct circle *nnew;
    while(a!=0)
    {
        if(!((a->x<=0)||(a->x>=SCREEN_W)||(a->y<=0)||(a->y>=SCREEN_H)))
        {
            struct circle *b = new circle;
            deepcopy(a,b);
            push(nnew,b);
        }
        pop(a);
    }
    a = nnew;
}
void push(struct circle*& a, struct circle* b)
{
    b->c=a;
    a = b;
}
void move(struct circle*& a)
{
    struct circle *b = a;
    while(b!=0)
    {
        b->x+=dx;
        b->y+=b->dy;
        b=b->c;
    }
}
int main(int argc, char **argv)
{
   top = 0;
   ALLEGRO_DISPLAY *display = NULL;
   ALLEGRO_EVENT_QUEUE *event_queue = NULL;
   ALLEGRO_TIMER *timer = NULL;
   ALLEGRO_BITMAP *bouncer = NULL;
   float bouncer_x = SCREEN_W / 2.0 - BOUNCER_SIZE / 2.0;
   float bouncer_y = SCREEN_H / 2.0 - BOUNCER_SIZE / 2.0;
   bool redraw = true;

   if(!al_init()) {
      fprintf(stderr, "failed to initialize allegro!\n");
      return -1;
   }

   if(!al_install_mouse()) {
      fprintf(stderr, "failed to initialize the mouse!\n");
      return -2;
   }

   timer = al_create_timer(1.0 / FPS);
   if(!timer) {
      fprintf(stderr, "failed to create timer!\n");
      return -3;
   }

   display = al_create_display(SCREEN_W, SCREEN_H);
   if(!display) {
      fprintf(stderr, "failed to create display!\n");
      al_destroy_timer(timer);
      return -4;
   }

   bouncer = al_create_bitmap(BOUNCER_SIZE, BOUNCER_SIZE);
   if(!bouncer) {
      fprintf(stderr, "failed to create bouncer bitmap!\n");
      al_destroy_display(display);
      al_destroy_timer(timer);
      return -5;
   }
   if(!al_init_primitives_addon())
   {
       fprintf(stderr,"primitives didn't load\n");
       return -6;
   }
   al_set_target_bitmap(bouncer);
   al_clear_to_color(al_map_rgb(255, 0, 255));
   al_draw_circle((float)BOUNCER_SIZE/2,(float)BOUNCER_SIZE/2,(float)BOUNCER_SIZE/3,al_map_rgb(255,255,255),3);
   al_set_target_bitmap(al_get_backbuffer(display));
   event_queue = al_create_event_queue();
   if(!event_queue) {
      fprintf(stderr, "failed to create event_queue!\n");
      al_destroy_bitmap(bouncer);
      al_destroy_display(display);
      al_destroy_timer(timer);
      return -1;
   }

   al_register_event_source(event_queue, al_get_display_event_source(display));
   al_register_event_source(event_queue, al_get_timer_event_source(timer));
   al_register_event_source(event_queue, al_get_mouse_event_source());
   al_clear_to_color(al_map_rgb(0,0,0));
   al_flip_display();
   al_start_timer(timer);

   while(1)
   {
      ALLEGRO_EVENT ev;
      al_wait_for_event(event_queue, &ev);

      if(ev.type == ALLEGRO_EVENT_TIMER) {
         redraw = true;
      }
      else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
         break;
      }
      else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES ||
              ev.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY) {

         bouncer_x = ev.mouse.x;
         bouncer_y = ev.mouse.y;
      }
      else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
          break;
      }
      if(redraw && al_is_event_queue_empty(event_queue)) {
         redraw = false;
         al_clear_to_color(al_map_rgb(0,0,0));
         //al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0);
         if(count(top)<=max)
         {
             add(top);
         }
         if(top==0)
         {
             throw "top is still 0";
         }
         // al_draw_bitmap(bouncer,a->x,a->y,0);
         struct circle *a = top;
         while (a->c!=0)
         {
             al_draw_bitmap(bouncer,a->x,a->y,0);
             if(a->c!=0)
             {
                 a=a->c;
             }
         }
         move(top);
         renew(top);
         al_flip_display();
      }
   }
   al_destroy_bitmap(bouncer);
   al_destroy_timer(timer);
   al_destroy_display(display);
   al_destroy_event_queue(event_queue);

   return 0;
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.