Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Losing physical memory after every execution...
#1
When I check the system resources after I run my program, I lose anywhere from 2 to 8 megs of physical memory. I don't know why, and this could easily become a problem (if it isn't already). Here is the code (c++ using MSVC & Allegro) and I know most of it sucks, but the important stuff to look at is the first part with global declarations and the clean_up() function:
Code:
#include "nupper.h"

player_struct *player = new player_struct;
enemy_struct *enemy = new enemy_struct[200];
object_struct *item = new object_struct[300];
BITMAP *btiles, *bnupp, *bichi, *bitems, *dbuff;
int map[19][550], is_debug = 1;
unsigned short campos = 20000;
int cur_set, cur_tile = 1;

void drawtile(BITMAP *to_buff, BITMAP *from_buff, int tile, int x, int y) { masked_blit(from_buff, to_buff, ((tile - 1) * 40), 0, x, y, 40, 40); }
void drawtile(BITMAP *to_buff, BITMAP *from_buff, int tile, int x, int y, int wx, int wy) { masked_blit(from_buff, to_buff, ((tile - 1) * wx), 0, x, y, wx, wy); }
void wait_fps(void) { while (ticks < 1 && !key[KEY_ESC]) yield_timeslice(); ticks=0; ++frames; }

void clean_up(void) {
    destroy_bitmap(btiles);
    destroy_bitmap(bnupp);
    destroy_bitmap(bichi);
    destroy_bitmap(bitems);
    destroy_bitmap(dbuff);
    delete player;
    delete[] enemy;
    delete[] item;
}

int init(void) {
    allegro_init();
      install_keyboard();
    install_timer();
    set_color_depth(16);
    if (set_gfx_mode(GFX_SAFE, 640, 480, 0, 0) != 0) {
        set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
        allegro_message("Unable to set graphic mode\n%s\n", allegro_error);
        return 1;
    }
    if (!(btiles = load_bmp(btiles, "gfx\\tiles.bmp"))) return 2;
    if (!(bnupp = load_bmp(bnupp, "gfx\\nupper.bmp"))) return 2;
    if (!(bichi = load_bmp(bichi, "gfx\\ichime.bmp"))) return 2;
    if (!(bitems = load_bmp(bitems, "gfx\\items.bmp"))) return 2;
    if (!(dbuff = create_bitmap(640,480))) {
        set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
        allegro_message("Unable to create 640x480 buffer!\n%s\n", allegro_error);
        return 2;
    };
    load_map("map.txt");
    clear(dbuff);
    LOCK_FUNCTION(second_counter);
    LOCK_VARIABLE(fps);
    LOCK_VARIABLE(frames);
    LOCK_FUNCTION(ticker);
    LOCK_VARIABLE(ticks);
    install_int_ex(second_counter, BPS_TO_TIMER(1));
    install_int_ex(ticker, BPS_TO_TIMER(400));    
    player->x = 100;
    player->y = 15000;
    install_mouse();
    for (int i = 0; i < 200; i++) {
        if (i <= 200) {
            enemy[i].hp = 0; enemy[i].ai = 0;
            enemy[i].grenades = 0; enemy[i].sleep = 0;
            enemy[i].speed = 0; enemy[i].spell_1 = 0;
            enemy[i].spell_2 = 0; enemy[i].spell_3 = 0;
            enemy[i].yen = 0;
        }
        item[i].kind = 0;
    }
    return 0;
}

BITMAP *load_bmp(BITMAP *buff, char *file) {
    buff = load_bitmap(file, NULL);
    if (!buff) {
        set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
        allegro_message("Error reading bitmap file '%s'\n", file);
        return NULL;
    }
    return buff;
}

void render(void) {
    int rcam = 0, mx = mouse_x, my = mouse_y;
    clear_to_color(dbuff, DBLUE);
    draw_map(dbuff, campos);
    if (is_debug) {
        if (campos > 0) rcam = campos / 40;
        textprintf(dbuff, font, 0, 0, WHITE, "FPS: %05d", fps);
        textprintf(dbuff, font, 0, 15, WHITE, "Cam Pos: %d, %d", campos, rcam);
    }
    rectfill(dbuff, 0, 440, 639, 479, BLUE);
    vline(dbuff, mx, my - 5, mouse_y + 5, WHITE);
    hline(dbuff, mx - 5, my, mouse_x + 5, WHITE);
    rect(dbuff, (mx / 40) * 40, (my / 40) * 40, 40 + (mx / 40) * 40, 40 + (my / 40) * 40, WHITE);
    
    if (cur_set == 1) textprintf(dbuff, font, 0, 460, WHITE, "SETTING TILE: %d", cur_tile);
    if (cur_set == 2) textout(dbuff, font, "SETTING PLAYER", 0, 460, WHITE);
    if (cur_set == 3) textprintf(dbuff, font, 0, 460, WHITE, "SETTING NPC: %d", cur_tile);
    if (cur_set == 4) textprintf(dbuff, font, 0, 460, WHITE, "SETTING OBJECT: %d", cur_tile);
    blit(dbuff,screen,0,0,0,0,640,480);
}

void update(void) {
    int but = mouse_b, i, ox, oy, sy, sx;
    if (key[KEY_UP] && !key[KEY_LSHIFT]) { cur_set--; rest(125); }
    if (key[KEY_DOWN] && !key[KEY_LSHIFT]) { cur_set++; rest(125); }
    if (key[KEY_UP] && key[KEY_LSHIFT]) { campos-=40; rest(125); }
    if (key[KEY_DOWN] && key[KEY_LSHIFT]) { campos+=40; rest(125); }
    if (cur_set > 4) cur_set = 4;
    if (cur_set < 1) cur_set = 1;
    if (key[KEY_RIGHT]) {
        cur_tile++;
        if (cur_tile > 11) cur_tile = 11;
        rest(125);
    }
    if (key[KEY_LEFT]) {
        cur_tile--;
        if (cur_tile < 1) cur_tile = 1;
        rest(125);
    }
    if (but & 1) {
        if (cur_set == 1) map[(mouse_x / 40)][(mouse_y / 40) + (campos / 40)] = cur_tile;
        
        if (cur_set == 2) {
            player->x = (mouse_x / 40) * 40;
            player->y = ((mouse_y / 40) * 40) + ((campos / 40) * 40);
        }
        
        if (cur_set == 3) {
            for (i = 0; i < 200; i++) {
                if (enemy[i].hp == 0) {
                    if (cur_tile == 1) {
                        enemy[i].x = (mouse_x / 40) * 40;
                        enemy[i].y = ((mouse_y / 40) * 40) + ((campos / 40) * 40);
                        enemy[i].buff = bichi;
                        enemy[i].hp = 2; enemy[i].dir = 1;
                        enemy[i].speed = 1; enemy[i].ai = 1;
                        rest(150); break;
                    }
                }
            }
        }
        
        if (cur_set == 4) {
            
        
        
        
        
        
        
        
        }
    }
    
    if (but & 2) {
        if (cur_set == 1) cur_tile = map[(mouse_x / 40)][(mouse_y / 40) + (campos / 40)];
        if (cur_set == 3) {
            for (i=0;i<200;i++) {
                if (enemy[i].hp) {
                    if ((((mouse_y / 40) * 40) + ((campos / 40) * 40)) == ((enemy[i].y / 40) * 40) && ((mouse_x / 40) * 40) == ((enemy[i].x / 40) * 40)) {
                        if (mouse_y > 220) { oy = -50; sy = -10; sx = -10; } else { oy = 0; sy = 10; sx = 60; }
                        if (mouse_x > 320) ox = -300; else ox = 0;
                        textprintf(screen, font, enemy[i].x + ox, (mouse_y + oy) + (1 * sy) + sx, WHITE, "HP: %d | SPEED: %d | AI: %d | Sleep: %d", enemy[i].hp, enemy[i].speed, enemy[i].ai, enemy[i].sleep);
                        textprintf(screen, font, enemy[i].x + ox, (mouse_y + oy) + (1 * sy) + sy + sx, WHITE, "Spell_1: %d | Spell_2: %d | Spell_3: %d", enemy[i].spell_1, enemy[i].spell_2, enemy[i].spell_3, enemy[i].grenades, enemy[i].yen);
                        textprintf(screen, font, enemy[i].x + ox, (mouse_y + oy) + (1 * sy) + (sy * 2) + sx, WHITE, "Grenades: %d | Yen: %d", enemy[i].grenades, enemy[i].yen);                                            
                        drawmsgbox(screen, mouse_x + (ox / 2), mouse_y + oy, "1) Speed", "2) AI/Sleep", "3) Spells/Grenades", "4) Yen", "5) Dir", "6) Delete");
                        while (!key[KEY_ENTER]) {
                            if (key[KEY_1]) get_input(enemy[i].speed, "Enemy speed (numeric keypad 0-9)");
                            if (key[KEY_2]) {
                                get_input(enemy[i].ai, "Enemy AI (numeric keypad 0-9)");
                                get_input(enemy[i].sleep, "Enemy Sleep (numeric keypad 0-9)");
                            }
                            if (key[KEY_3]) {
                                get_input(enemy[i].spell_1, "Enemy spell_1 (numeric keypad 0-9)");
                                get_input(enemy[i].spell_2, "Enemy spell_2 (numeric keypad 0-9)");
                                get_input(enemy[i].spell_3, "Enemy spell_3 (numeric keypad 0-9)");
                                get_input(enemy[i].grenades, "Enemy grenades (numeric keypad 0-9)");
                            }
                            if (key[KEY_4]) get_input(enemy[i].yen, "Enemy yen (numeric keypad 0-9)");
                            if (key[KEY_5]) get_input(enemy[i].dir, "Enemy dir (numeric keypad 0-9)");
                            if (key[KEY_6]) {
                                enemy[i].hp = 0; break;
                            }
                        }    
                    }
                }
            }
        }
    }
}

void draw_map(BITMAP *b, int sy) {
    int y = (sy / 40), offy = (sy % 40), i;
    for (int x = 0; x <= 19; x++) {
        for (int yy = y; yy < y + 12; yy++) if (map[x][yy]) drawtile(b, btiles, map[x][yy], (x * 40), ((yy - y) * 40) - offy);
    }
    if (player->y - sy > 0 && player->y - sy < 440) drawtile(b, bnupp, 2, player->x, (player->y - sy), 32, 32);
    
    for (i = 0; i < 200; i++) {
        if (enemy[i].hp) {
            if (enemy[i].y - sy >= 0 && enemy[i].y - sy < 440) drawtile(b, enemy[i].buff, 7, enemy[i].x, (enemy[i].y - sy));
        }
    }
}

int load_map(string s) {
    ifstream file_in;
    file_in.open(s.c_str());
    if (!file_in.is_open()) return 1;
    int total_x = 0, total_y = 0;
    file_in >> total_x >> total_y;    
    for(int y=0; y!=total_y; y++) for(int x = 0; x!=total_x; x++) file_in >> map[x][y];
    file_in.close();
    return 0;
}


void drawmsgbox(BITMAP *b, int x1, int y1, char *text1, char *text2, char *text3, char *text4, char *text5, char *text6) {
    int ysize = 0, xsize = 5, biggest = 0;
    if (strlen(text1)) ysize+=11;
    if (strlen(text2)) ysize+=11;
    if (strlen(text3)) ysize+=11;
    if (strlen(text4)) ysize+=11;
    if (strlen(text5)) ysize+=11;
    if (strlen(text6)) ysize+=11;
    if (strlen(text1) > biggest) biggest = strlen(text1);
    if (strlen(text2) > biggest) biggest = strlen(text2);
    if (strlen(text3) > biggest) biggest = strlen(text3);
    if (strlen(text4) > biggest) biggest = strlen(text4);
    if (strlen(text5) > biggest) biggest = strlen(text5);
    if (strlen(text6) > biggest) biggest = strlen(text6);
    rectfill(b, x1, y1, x1 + (biggest * 10), y1 + ysize, 0);
    textout(b, font, text1, x1 + 5, y1 + 5, WHITE);
    textout(b, font, text2, x1 + 5, y1 + 15, WHITE);
    textout(b, font, text3, x1 + 5, y1 + 25, WHITE);
    textout(b, font, text4, x1 + 5, y1 + 35, WHITE);
    textout(b, font, text5, x1 + 5, y1 + 45, WHITE);
    textout(b, font, text6, x1 + 5, y1 + 55, WHITE);
}

void get_input(int &i, char *printwhat) {
    clear(screen);
    textout(screen, font, printwhat, 0, 0, WHITE);
    while (key[KEY_1] || key[KEY_2] || key[KEY_3] || key[KEY_4] || key[KEY_5] || key[KEY_6] || key[KEY_7] || key[KEY_8] || key[KEY_9] || key[KEY_0]);
    while (1) {
        if (key[KEY_0]) { i = 0; break; }
        if (key[KEY_1]) { i = 1; break; }
        if (key[KEY_2]) { i = 2; break; }
        if (key[KEY_3]) { i = 3; break; }
        if (key[KEY_4]) { i = 4; break; }
        if (key[KEY_5]) { i = 5; break; }
        if (key[KEY_6]) { i = 6; break; }
        if (key[KEY_7]) { i = 7; break; }
        if (key[KEY_8]) { i = 8; break; }
        if (key[KEY_9]) { i = 9; break; }
    }
    textout(screen, font, "press any key", 0, 10, WHITE);
    clear_keybuf();
    while (key[KEY_1] || key[KEY_2] || key[KEY_3] || key[KEY_4] || key[KEY_5] || key[KEY_6] || key[KEY_7] || key[KEY_8] || key[KEY_9] || key[KEY_0]);
    readkey();
}

int main(void) {
    if (int i = init()) return i;
    while (!key[KEY_ESC]) {
        update();
        render();
        wait_fps();
    }
    clean_up();
    return 0;
}
END_OF_MAIN()
am: "Where should I put this thing so that it doesn't hurt anyone we know or care about?"
Max:"Out the window, Sam. There's nobody but strangers out there."
Reply
#2
Okay, there was a large thread about this over at allegro.cc basically to summarize, someone belived their was a flaw with the allegro.dll being freed every run, which was causing memory loss, and reported it under MSVC as well, not under Mingw32. 8MB is a large amount, amount of memory and it doesnt look like your allocating anything close.

Are you running windows 98? and ill post a link to the thread.

Finally, your clean_up struct looks fine.

[EDIT]
Allright heres the link, and i'll quote some important parts that may be of help
http://www.allegro.cc/forums/view_thread.php?_id=280490

Quote:OK, there is nothing wrong with allegro on it's own. Like gillius proposed I made this quite empty test program that only initializes allegro stuff. I made a batch file and ran it hundreds of times. "Free Memory" readout decreases 150kB per run, until it reaches 7 Megs. The whole system keeps working just fine, I can run for example "Ghost Recon", and afterwards "Free Memory" jumps back to 130MB.

Summary: No Error whatsoever!
and.. I should have done this earlier.
Allright so it wasnt allegros fault keep reading...

Quote:Yes Windows may not actually free any memory until it needs to. So memory may be available but it hasn't checked to make sure that's the case.

When you "delete" something, there's never a reason to actually delete it, JUST in case you use it again. But when you run out of memory then you need to clean it up. That may be what is happening here, although the fact that it decreases each time is interesting because if it can't reuse the memory from the Allegro DLL then maybe what I'm saying isn't correct?
Quote:Another possibility may be that Windows isn't releasing the Allegro .dll fully. IIRC, by default Windows waits a while after a .dll is released before it actually releases the memory, in case another program comes up that wants it. There are ways to make it release immediately, though.

Try overloading new so it keeps track of how much memory is allocated and delete to find out how much memory is being freed, and then you can find if the memory leak is your fault or not.
b]Hard Rock[/b]
[The Stars Dev Company] [Metal Qb flopped] [The Terror]
Stop Double Posts!
Whats better? HTML or Variables?
Reply
#3
I dunno if this can be the reason, but some MSVC runtimes are huge and are there just for the like to be there.
SCUMM (the band) on Myspace!
ComputerEmuzone Games Studio
underBASIC, homegrown musicians
[img]http://www.ojodepez-fanzine.net/almacen/yoghourtslover.png[/i
Reply
#4
I just ran a return to castle wolfenstein and then exited it. When I checked the systems physical memory I got 279 which is up almost 20 megs, so I don't know if I have a problem at all.

Anyways, to overload the new and delete functions, how would I do that. I know how to overload my own functions, but not others.

Code:
int new(void *ptr, void refer, array_num) {
     ptr = new refer[array_num];
     return sizeof(ptr);
}
I don't think that'll work at all. And since I'm probably so far off base, I'm not going to try to do the delete function.
am: "Where should I put this thing so that it doesn't hurt anyone we know or care about?"
Max:"Out the window, Sam. There's nobody but strangers out there."
Reply
#5
overloading new

Code:
void *operator new(size_t size)
{
void *p;
p = malloc(size);
if(!p){
bad_alloc ba;
throw ba;
}
return p;
}
void operator delete(void *p)
{
free(p);
}
Note this does not overload delete []p and new[], youlll have to overload those as well.
b]Hard Rock[/b]
[The Stars Dev Company] [Metal Qb flopped] [The Terror]
Stop Double Posts!
Whats better? HTML or Variables?
Reply
#6
How come when I change the number of elements for items to 400 it crashes when it deletes them in the clean_up function. I don't want to post the whole program again, so let me say that I did checking to enable me to up the number of elements and I made a line in the init function that says: if (items == NULL) return 3; which would make the program error out. The exact same code works with 200, but not with 400. That is wierd. Any takers?
am: "Where should I put this thing so that it doesn't hurt anyone we know or care about?"
Max:"Out the window, Sam. There's nobody but strangers out there."
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)