2011-04-14 2 views
1

나는 다음과 같은 구조체와 함수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; 
} 

, 나는이 방법에서 구조체의 배열을받는 문제에 직면하고있어이 있습니다

/* 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()는 두 가지 방법의 출력을 비교 ->,536,913,632 방법 항목 10 (발신자)

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 바로 여기에 있습니다 : : 당신은 스택에 cn을 allocting하고

struct cell cn[8]; 

그래서 당신의 cellGetNeighbors 기능이 완료 복귀는 무슨 내가 잘못 .. 감사합니다 .. 뭐하는 거지 cn (cellGetNeighbors 버전)의 값은 더 이상 유효하지 않으며 (cellMinNeighbor)은 다른 용도로 사용되는 스택의 청크를 가리 킵니다.

당신이 쉽게 가지 옵션이 있습니다 :

  1. 발신자가 메모리를 할당 할 책임이 그래서 cellGetNeighbors에 팔 struct cell의 배열을 전달합니다.
  2. cellGetNeighbors 안에 힙 (즉, malloc)에 cn을 할당하고 지금 그대로 돌려 보내십시오. 호출자는 물론 완료 될 때 freecellGetNeighbors 반환 값을 가져야합니다.이 사실은 cellGetNeighbors 인터페이스의 일부로 문서화되어야합니다.

두 번째 옵션을 권하고 싶습니다. 단 하나의 셀을 적절히 비우려면 별도의 cellFree 함수를 만드는 것이 좋습니다. struct cell에 포인터가 있고 그 포인터를 해제해야하기 때문에 cellFree 함수는 좋은 생각입니다. 정확히 8 개의 요소가없는 배열을 사용해야 할 경우 더 복잡합니다. 그럴 경우 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; 

또한, I 이후 이미 여기에 책을 쓰고 있다면 malloc (또는 calloc 또는 realloc 또는 void *을 반환하는 모든 항목)을 C로 캐스팅 할 필요가 없으므로 문제를 해결할 수 있습니다.

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에 대한 누수가 유출되었습니다. 즉 포인터 (즉 cellCopyValues 플러스 keys의 할당)의로 keys에 대한 데이터를 할당

for(i = 0; i < 8; i++) { 
    cellDuplicateContent(c, &cn[i]); 
} 

그리고 cellDuplicateContent 그냥 물론, 개별 구성원을 복사 한 것입니다 : 당신은 더 이런 식으로 뭔가 더 나을 것 .

+0

감사합니다. 나는 당신의 제안 대부분을 구현했습니다. 나는 여전히 cellFree에 관한 문제에 직면하고있다. - 나는 그것에 대한 독립적 인 질문을 게시했다. 다시 한번 감사한다.) – Bojack

1

cellGetNeighbors가 스택 메모리를 반환하는 것처럼 보입니다. & cn [0]을 가리키는 cptr을 반환합니다. 메서드가 반환되면 스택에서 선언 한 내용은 더 이상 유효하지 않습니다. 당신은 그 안에 셀을 복사하고 있기 때문에 배열을 malloc-up 할 필요가있을 것입니다. 궁극적으로 해당 배열을 해제해야합니다.

관련 문제