tags:

views:

101

answers:

2

I'm attempting to write a solver for a particular puzzle. It tries to find a solution by trying every possible move one at a time until it finds a solution. The first version tried to solve it depth-first by continually trying moves until it failed, then backtracking, but this turned out to be too slow. I have rewritten it to be breadth-first using a queue structure, but I'm having problems with memory management.

Here are the relevant parts:

int main(int argc, char *argv[])
{
    ...
    int solved = 0;
    do {
        solved = solver(queue);
    } while (!solved && !pblListIsEmpty(queue));
    ...
}

int solver(PblList *queue) {
    state_t *state = (state_t *) pblListPoll(queue);

    if (is_solution(state->pucks)) {
        print_solution(state);
        return 1;
    }

    state_t *state_cp;
    puck new_location;
    for (int p = 0; p < puck_count; p++) {
        for (dir i = NORTH; i <= WEST; i++) {
            if (!rules(state->pucks, p, i)) continue;
            new_location = in_dir(state->pucks, p, i);
            if (new_location.x != -1) {
                state_cp = (state_t *) malloc(sizeof(state_t));
                state_cp->move.from = state->pucks[p];
                state_cp->move.direction = i;
                state_cp->prev = state;
                state_cp->pucks = (puck *) malloc (puck_count * sizeof(puck));
                memcpy(state_cp->pucks, state->pucks, puck_count * sizeof(puck)); /*CRASH*/
                state_cp->pucks[p] = new_location;
                pblListPush(queue, state_cp);
            }
        }
    }

    free(state->pucks);

    return 0;
}

When I run it I get the error:

ice(90175) malloc: *** mmap(size=2097152) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
Bus error

The error happens around iteration 93,000. From what I can tell, the error message is from malloc failing, and the bus error is from the memcpy after it.

I have a hard time believing that I'm running out of memory, since each game state is only ~400 bytes. Yet that does seem to be what's happening, seeing as the activity monitor reports that it is using 3.99GB before it crashes. I'm using http://www.mission-base.com/peter/source/ for the queue structure (it's a linked list).

Clearly I'm doing something dumb. Any suggestions?

+2  A: 

Check the result of malloc. If it's NULL, you might want to print out the length of that queue.

Also, the code snippet you posted didn't include any frees...

kwatford
the result is NULL. The length of the queue is ~9 million (christ...)
maxdj
@maxdj: Well, 9m * 400 = ~3.6b, which is what you expected, right?
James McNellis
Well 400 bytes * 9e6 would close to run you out of memory. Do you ever remove items from the queue? It's possible that the breadth first algorithm actually uses more memory than you're able to give it. You may need to split the work into more pieces.
Mark B
@James: yeah, I guess so. The problem is that I can't free previous states entirely, because I need to know which steps were taken to get to the solution.
maxdj
@maxdj Then you either need to go back to depth-first search or use a pruned search tree of some sort. A* maybe.
kwatford
@kwatford: Ok, thanks I'll look into that
maxdj
+1  A: 

You need to free() the memory you've allocated manually after you're done with it; dynamic memory doesn't just "free itself"

Delan Azabani