n a*_*n a 1 c arrays struct pointers
我有以下结构和功能
// 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;
}
Run Code Online (Sandbox Code Playgroud)
现在,我遇到了从这个方法接收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;
}
Run Code Online (Sandbox Code Playgroud)
..进入这种方法 -
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();
}
Run Code Online (Sandbox Code Playgroud)
当我比较两种方法中的cellPrintData()输出时 - > method1 :( sender)
CELL
.............
27.203030
71.435282
34.713147
0.000050
999.000000
34.713197
34.713147
Run Code Online (Sandbox Code Playgroud)
方法2 :(接收者)
CELL
.............
27.203030
71.435282
34.713147
0.000050
999.000000
0.000000
0.000000
Run Code Online (Sandbox Code Playgroud)
这也导致k1和k2的非常大的值 - 以及分段错误.我做错了什么..谢谢.. :)
你的问题就在这里cellGetNeighbors
:
struct cell cn[8];
Run Code Online (Sandbox Code Playgroud)
你allocting cn
在堆栈上,所以当你的cellGetNeighbors
函数执行完毕并返回的值cn
(在cellGetNeighbors
它的版本)将不再有效,并且cn
在cellMinNeighbor
将在正在使用其他的东西堆了一大块被人指指点点.
你有两个简单的选择:
struct cell
成cellGetNeighbors
使得呼叫者负责分配该内存.cn
在堆(即malloc
)内部分配,cellGetNeighbors
并像现在一样返回它.呼叫者会,当然,必须free
在cellGetNeighbors
返回值当它完成它(这个事实应该被记录为部分cellGetNeighbors
接口).我建议第二个选项,我建议建立一个单独的cellFree
功能来正确释放单个单元格.该cellFree
函数是一个好主意,因为你struct cell
的指针在其中,并且需要释放指针.当然,如果您需要使用一个不具有八个元素的数组,这将进一步复杂化; 如果发生这种情况,那么你必须通过添加额外的指针参数来返回数组大小getCellNeighbors
.如果事情到达那一点,那么你将需要添加一个单独的结构:
struct cells {
int n; /* How many cells there are */
struct cell *items; /* The cells themselves */
}
Run Code Online (Sandbox Code Playgroud)
以及一组用于分配和释放这些新结构的函数.
我猜你也有类似的堆栈与堆问题cellCalculateKey
.
而且,您不需要这样做:
struct cell *cptr = &cn[0];
cellPrintData(&cn[2]);
return cptr;
Run Code Online (Sandbox Code Playgroud)
在cn
没有你干预的情况下,数组会衰减为指针,这很好:
cellPrintData(&cn[2]);
return cn;
Run Code Online (Sandbox Code Playgroud)
此外,由于我已经在这里写了一本书,你不需要在C中转换malloc
(或者calloc
或者realloc
其他任何返回的void *
)返回,这样做可以掩盖问题.所以,你说的地方:
struct cell *c2 = (struct cell *) malloc(sizeof(struct cell));
/* ... */
c2->keys = (struct keys *) malloc(sizeof(struct key));
Run Code Online (Sandbox Code Playgroud)
你应该说:
struct cell *c2 = malloc(sizeof(struct cell));
/* ... */
c2->keys = malloc(sizeof(struct key));
Run Code Online (Sandbox Code Playgroud)
另外,你有一个内存泄漏:
for(i = 0; i < 8; i++) {
cn[i] = *cellDuplicate(c);
}
Run Code Online (Sandbox Code Playgroud)
cellDuplicate
分配给新的内存struct cell
泄露.你会更喜欢这样的东西:
for(i = 0; i < 8; i++) {
cellDuplicateContent(c, &cn[i]);
}
Run Code Online (Sandbox Code Playgroud)
并且cellDuplicateContent
只会复制单个成员,当然,分配数据keys
作为指针(即cellCopyValues
加上分配keys
).