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

问题描述

| 我有以下结构和功能
// 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,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;
}
..进入此方法-
struct cell * cellMinNeighbor(struct cell *c,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()输出时-> 方法1 :(发送方)
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的值非常大,以及分段错误。我在做什么错..谢谢..:)     

解决方法

您的问题就在
cellGetNeighbors
中:
struct cell cn[8];
您正在堆栈上分配
cn
,因此当
cellGetNeighbors
函数完成并返回时,
cn
的值(
cellGetNeighbors
版本)将不再有效,
cellMinNeighbor
中的
cn
将指向堆栈的一部分,即被用于其他东西。 您有两个简单的选择: 将由八个ѭ13array组成的数组传递到
cellGetNeighbors
中,以便调用者负责分配该内存。 在
cellGetNeighbors
内的堆(即
malloc
)上分配
cn
并按原样返回。当然,调用者在完成返回值时必须将
cellGetNeighbors
返回值value18ѭ(并且此事实应作为
cellGetNeighbors
接口的一部分进行记录)。 我建议第二个选项,我建议构建一个单独的ѭ21函数以正确释放单个单元格。
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;
此外,由于我已经在这里写书了,所以您无需在C中使用
malloc
(或
calloc
realloc
或其他返回
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);
}
ѭ37为新的ѭ13分配的内存泄漏。您最好使用类似以下的方法:
for(i = 0; i < 8; i++)  {
    cellDuplicateContent(c,&cn[i]);
}
而ѭ40just只会复制单个成员,并且当然为
keys
分配数据,因为这是一个指针(即
cellCopyValues
加上
keys
的分配)。     ,看起来cellGetNeighbors正在返回堆栈内存-它返回cptr,它指向&cn [0]。方法返回后,您在堆栈上声明的所有内容将不再有效。您正在将单元格复制到其中,因此您可能仅需要分配阵列。请注意,您最终还需要释放该数组。