开发者

C: Freeing a malloc'd array at the wrong time?

开发者 https://www.devze.com 2023-02-26 05:41 出处:网络
I have a struct cell -> struct cell { double x, y, h, g, rhs; struct key *keys; }; And I\'m using the following method to free a cell ->

I have a struct cell ->

struct cell {
    double x, y, h, g, rhs;
    struct key *keys;
};

And I'm using the following method to free a cell ->

void cellFree(struct cell *c)   {
    // Free the keys
    free(c->keys);

    // Free the cell itself.
    free(c);
}

void cellFreeSors(struct cell *cn)  {
    int i;
    for(i = 0; i < 5; i++)  {
        // Free keys
        free(cn[i].keys);
    }
    // Free array
    free(cn);
}

Now, I'm facing a weird problem with one of the malloc'd arrays I've created. Basically, I'm trying to find the neighbors of a cell and doing some processing based on their values using the following two methods ->

struct cell * cellGetSuccessors(struct cell *c, struct cell *sstart, struct cell *sgoal, double km) {
        int i;

        // CREATE 5 CELLS
        struct cell *cn = malloc(5 * sizeof (struct cell));
            if (cn == NULL) {
            printf("--> Unable to malloc *cn!\n");
            errno = ENOMEM;
            return NULL;
            }

        for(i = 0; i < 5; i++)  {
            cn[i].keys = malloc(sizeof(struct key));
                if (cn[i].keys == NULL) {
                printf("--> Unable to malloc *cn[%d].keys!\n", i);
                errno = ENOMEM;
                return NULL;
            }
            cellCopyValues(&cn[i], c);
        }

        // MAKE THEM NEIGHBORS
        // PROCESS

        return cn;
    }


    double cellRHS(struct cell *c, struct cell *sstart, struct cell *sgoal, double km, struct cell * prevCell)  {
        // GET NEIGHBORS of c
        struct cell *cn = cellGetSuccessors(c, sstart, sgoal, km);
        double minsum;

        // SOME PROCESS TO UPDATE minsum
        minsum = 5.232111; // SAY

        // Free memory
        cellFreeSors(cn);

        return minsum;
    }

Trouble is, when I call cellFreeSors() in cellRHS(), I run into problems later.. This is how these functions are called..

struct cell *u = cellCreateNew();
u->rhs = cellRHS(u, sstart, sgoal, km, prevCell);
queueAdd(&U, u);

This gives me a segmentation error when I try to print my queue ->

    QUEUE CONTENTS
    ============================================================开发者_StackOverflow社区======
    F -> 0x2354550
    L - >0x2354550
    (1) [0x2354550] X 50.000000, Y 45.000000    PREV: (nil) NEXT: 0x4014000000000000
Segmentation fault

As you can see, the NEXT for the entry seems to be initialized for some reason. The same code when executed WITHOUT cellRHS() works fine .. ->

struct cell *u = cellCreateNew();
queueAdd(&U, u);

    QUEUE CONTENTS
    ==================================================================
    F -> 0x2354550
    L - >0x2354550
    (1) [0x2354550] X 50.000000, Y 45.000000    PREV: (nil) NEXT: (nil)

Why is cellFreeSors() causing this problem? I've no use for the spawned neighbors of u beyond the scope of cellRHS. What am I doing wrong?

Thanks..

** EDITS The struct for queue_node is

/* QUEUE NODE
 * ----------------------------
 * Contains a struct cell c and
 * reference to next queue_node
 */
struct queue_node   {
    struct cell *c;
    struct queue_node *next;
    struct queue_node *prev;
};

/* PRIORITY QUEUE
 * ----------------------------
 * The queue itself, with first
 * and last pointers to queue_nodes
 */
struct priority_queue   {
    struct queue_node *first;
    struct queue_node *last;
};

The queuePrint() method shows queue contents ->

void queuePrint(struct priority_queue *q)
{
    printf("\n\n\tQUEUE CONTENTS\n\t==================================================================\n");
    int i = 1;
    struct queue_node *temp = q->first;
    printf("\tF -> %p\n\tL -> %p\n", q->first, q->last);
    while(temp != NULL) {
        printf("\t(%d) [%p]\tX %f, Y %f\tPREV: %p\tNEXT: %p", i, temp, temp->c->x, temp->c->y, temp->prev, temp->next);
        printf("\n");
        temp = temp->next;
        i++;
    }
    printf("\n\n");
}


Some suggestions here:

  1. Use a centralized allocCell() and freeCell() method. This allows you to trace each allocated and deallocated cell exactly.

  2. Put an id on each cell. Again, this allows detailed tracing. You can compile it one way for production and another for debug if space is an issue.

  3. Write tracing routines for the cell, to see that your routines are only freeing allocated cells, that any cell is only freed once, etc. You could even write a hashtable to store the id's of allocated and freed cells (of course just during debug) and write verification checks.

  4. You are probably going to run into memory errors again if you don't do this.

  5. Even if you do this, you will run into memory errors again, but these tools will help you track it down faster next time.

  6. Switch to C# or java and don't free anything :)

0

精彩评论

暂无评论...
验证码 换一张
取 消