C:无法接收结构数组的指针

时间:2011-04-14 00:29:05

标签: c arrays pointers struct

我有以下结构和功能

// KEY
// ----------------------------
struct key  {
    double k1, k2;
};

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

void cellPrintData(struct cell *c)  {
    printf("\n\tCELL\n\t.............\n");
    printf("\t%f\n", c->x);
    printf("\t%f\n", c->y);
    printf("\t%f\n", c->g);
    printf("\t%f\n", c->h);
    printf("\t%f\n", c->rhs);
    printf("\t%f\n", c->keys->k1);
    printf("\t%f\n", c->keys->k2);
}

/* cellCopyValues
 * ----------------------------
 * Copy values from source cell
 * into target cell.
 */
void cellCopyValues(struct cell *targetcell, struct cell *sourcecell)   {

    targetcell->x = sourcecell->x;  
    targetcell->y = sourcecell->y;  
    targetcell->h = sourcecell->h;  
    targetcell->g = sourcecell->g;  
    targetcell->rhs = sourcecell->rhs;  
    targetcell->keys->k1 = sourcecell->keys->k1;    
    targetcell->keys->k2 = sourcecell->keys->k2;    

}

/* cellDuplicate
 * ----------------------------
 * Create a duplicate cell using
 * values from given cell and return it.
 */
struct cell * cellDuplicate(struct cell *c) {


    struct cell *c2 = (struct cell *) malloc(sizeof(struct cell));
        if (c2 == NULL) {
        printf("--> Unable to malloc *c2!\n");
        errno = ENOMEM;
        return NULL;
        }
    c2->keys = (struct key *) malloc(sizeof(struct key));
        if (c2->keys == NULL) {
        printf("--> Unable to malloc *c2->keys!\n");
        errno = ENOMEM;
        return NULL;
        }
    cellCopyValues(c2, c);

    return c2;
}

现在,我在使用此方法接收struct数组时遇到了问题:

/* cellGetNeighbors()   
 * ----------------------------
 * Gets the neighbors of a cell
 */
struct cell * cellGetNeighbors(struct cell *c, struct cell *sstart, struct cell *sgoal, double km)  {

    int i;

    // CREATE 8 CELLS
    struct cell cn[8];

    //cellPrintData(c);

    for(i = 0; i < 8; i++)  {
        cn[i] = *cellDuplicate(c);
    }

    // MAKE THEM NEIGHBORS

    cn[0].y -= _DISTANCETOMOVE;
    cn[1].x -= _DISTANCETOMOVE;
    cn[2].y += _DISTANCETOMOVE;
    cn[3].x += _DISTANCETOMOVE;

    cn[4].x -= _DISTANCETOMOVE;
    cn[4].y -= _DISTANCETOMOVE;

    cn[5].x -= _DISTANCETOMOVE;
    cn[5].y += _DISTANCETOMOVE;

    cn[6].x += _DISTANCETOMOVE;
    cn[6].y += _DISTANCETOMOVE;

    cn[7].x += _DISTANCETOMOVE;
    cn[7].y -= _DISTANCETOMOVE;



    // CALCULATE g, h, rhs, key
    for(i = 0; i < 8; i++)  {
        cn[i].g = cellG(&cn[i], sgoal);
        cn[i].h = cellH(&cn[i], sstart);
        cn[i].rhs = _INFINITY;

        cn[i].keys = cellCalculateKey(&cn[i], km);
        //cellPrintData(&cn[i]);
    }

    // STORE THESE NEIGHBORS IN FILE.
    struct cell *cptr = &cn[0];
    cellPrintData(&cn[2]);
    return cptr;
}

..进入THIS方法 -

struct cell * cellMinNeighbor(struct cell *c, struct cell *sstart, struct cell *sgoal, double km)   {

    // GET NEIGHBORS of c
    int i;
    struct cell *cn = cellGetNeighbors(c, sstart, sgoal, km);
    double sum[8];
    double minsum;
    int mincell;

cellPrintData(cn + 2);

    for(i = 0; i < 8; i++)  {
    //  sum[i] = 0.00;
    //  sum[i] += cellCost(c, cn + i);
    //  sum[i] += cellG(cn + i, sgoal);
    }
/*
    // Find min sum
    minsum = sum[0];
    mincell = 0;    
    for(i = 0; i < 8; i++)  {
        if(minsum < sum[i]) {
            minsum = sum[i];
            mincell = i;        
        }
    }

    //return (cn+mincell);
*/
    return cellCreateNew();
}   

当我比较两种方法中的cellPrintData()输出时 - &gt; method1 :(发件人)

CELL
.............
27.203030
71.435282
34.713147
0.000050
999.000000
34.713197
34.713147

方法2 :(接收者)

CELL
.............
27.203030
71.435282
34.713147
0.000050
999.000000
0.000000
0.000000

这也导致k1和k2的非常大的值 - 以及分段错误。我做错了什么..谢谢.. :))

2 个答案:

答案 0 :(得分:7)

您的问题就在cellGetNeighbors

struct cell cn[8];

您正在堆栈上分配cn,所以当您的cellGetNeighbors函数完成并返回时,cncellGetNeighbors版本的值)的值将为no更长时间有效且cn中的cellMinNeighbor将指向正在用于其他内容的堆栈块。

您有两个简单的选择:

  1. 将八个struct cell的数组传递给cellGetNeighbors,以便调用者负责分配该内存。
  2. cn内的堆上(即malloc)分配cellGetNeighbors并按原样返回。当然,调用者在完成它时必须free cellGetNeighbors返回值(这个事实应该记录为cellGetNeighbors接口的一部分)。
  3. 我建议使用第二个选项,我建议构建一个单独的cellFree函数来正确释放单个单元格。 cellFree函数是个好主意,因为struct cell中有一个指针,需要释放该指针。当然,如果您需要使用一个不具有八个元素的数组,这将进一步复杂化;如果发生这种情况,那么你必须通过向getCellNeighbors添加额外的指针参数来返回数组大小。如果事情到达那一点,那么你将需要添加一个单独的结构:

    struct cells {
        int n; /* How many cells there are */
        struct cell *items; /* The cells themselves */
    }
    

    和一组用于分配和释放这些新结构的函数。

    我猜你也有cellCalculateKey类似的堆栈与堆的问题。

    而且,您不需要这样做:

    struct cell *cptr = &cn[0];
    cellPrintData(&cn[2]);
    return cptr;
    

    cn数组会在没有您干预的情况下衰减为指针,这很好:

    cellPrintData(&cn[2]);
    return cn;
    

    此外,由于我已经在这里写了一本书,你不需要从malloc(或callocrealloc或其他任何返回{{{ C中的1}}}这样做可以掩盖问题。所以,你这么说:

    void *
    你应该说:

    struct cell *c2 = (struct cell *) malloc(sizeof(struct cell));
    /* ... */
    c2->keys = (struct keys *) malloc(sizeof(struct key));
    

    另一件事,你在这里有内存泄漏:

    struct cell *c2 = malloc(sizeof(struct cell));
    /* ... */
    c2->keys = malloc(sizeof(struct key));
    

    for(i = 0; i < 8; i++) { cn[i] = *cellDuplicate(c); } 为新cellDuplicate分配的内存被泄露。你会更喜欢这样的事情:

    struct cell

    for(i = 0; i < 8; i++) { cellDuplicateContent(c, &cn[i]); } 只会复制个别成员,当然,还会为cellDuplicateContent分配数据,因为它是一个指针(即keys加上cellCopyValues的分配)

答案 1 :(得分:1)

看起来cellGetNeighbors正在返回堆栈内存 - 它返回cptr,它指向&amp; cn [0]。方法返回后,您在堆栈上声明的任何内容都将不再有效。你正在将单元格复制到那里,所以你可能只需要对数组进行malloc-up。请注意,您最终也需要释放该数组。

相关问题