2011-04-14 66 views
1

我有以下結構和功能C:無法接收一個指向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; 
} 

現在,我在此方法接收結構陣列面臨的一個問題:

/* 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; 
} 

..到這個方法 -

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()在兩種方法輸出 - > 方法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非常大的值 - 和段故障。我在做什麼錯了..謝謝..:)

回答

7

你的問題就在這裏cellGetNeighbors

struct cell cn[8]; 

你在棧上allocting cn所以當你的cellGetNeighbors功能結束,返回時,值cn(它的cellGetNeighbors版本)將不再有效,並且cn將在cellMinNeighbor中指向正在用於其他內容的堆棧塊。

你有兩個簡單的選擇:

  1. 傳八struct cell一個數組cellGetNeighbors使主叫方負責分配內存。
  2. cellGetNeighbors之內的堆(即malloc)上分配cn並按照現在的樣子返回它。當它結束時,調用者當然必須得到freecellGetNeighbors返回值(並且這個事實應該被記錄爲cellGetNeighbors接口的一部分)。

我建議第二個選項,我建議建立一個單獨的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; 

此外,由於我我已經在這裏寫了一本書,你不需要在C中從malloc(或callocrealloc或其他任何返回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因爲這是一個指針(即cellCopyValueskeys分配) 。

+0

謝謝。我已經實施了大部分建議。我仍然面臨一個關於cellFree的問題,但是我已經發布了一個獨立的問題。再次感謝:) – Bojack 2011-04-14 05:13:54

1

看起來像cellGetNeighbors正在返回堆棧內存 - 它返回cptr,它指向& cn [0]。一旦該方法返回,您在堆棧中聲明的任何內容都不再有效。您將單元格複製到該單元格中,因此您可能只需要將該單元格組裝起來。請注意,您需要最終釋放該陣列。