2010-11-29 2 views
0

이 코드는 간헐적으로 작동합니다. 소형 마이크로 컨트롤러에서 실행됩니다. 프로세서를 다시 시작한 후에도 정상적으로 작동하지만 코드의 일부분을 변경하면 끊어집니다. 이것은 내가 어떤 종류의 포인터 버그 또는 메모리 손상이라고 생각하게 만듭니다. 일어나는 일은 좌표입니다. p_res.pos.x는 write_circle_outlined에 전달 될 때 때때로 0 (잘못된 값)과 96 (올바른 값)으로 읽혀집니다. y는 대부분 올바른 것으로 보입니다. 누군가 분명히 잘못을 지적 할 수 있다면 그것을 지적하십시오!간헐적 인 버그 - 때로는이 코드가 작동하고 때때로 그렇지 않습니다!

int demo_game() 
{ 
    long int d; 
    int x, y; 
    struct WorldCamera p_viewer; 
    struct Point3D_LLA p_subj; 
    struct Point2D_CalcRes p_res; 
    p_viewer.hfov = 27; 
    p_viewer.vfov = 32; 
    p_viewer.width = 192; 
    p_viewer.height = 128; 
    p_viewer.p.lat = 51.26f; 
    p_viewer.p.lon = -1.0862f; 
    p_viewer.p.alt = 100.0f; 
    p_subj.lat = 51.20f; 
    p_subj.lon = -1.0862f; 
    p_subj.alt = 100.0f; 
    while(1) 
    { 
     fill_buffer(draw_buffer_mask, 0x0000); 
     fill_buffer(draw_buffer_level, 0xffff); 
     compute_3d_transform(&p_viewer, &p_subj, &p_res, 10000.0f); 
     x = p_res.pos.x; 
     y = p_res.pos.y; 
     write_circle_outlined(x, y, 1.0f/p_res.est_dist, 0, 0, 0, 1); 
     p_viewer.p.lat -= 0.0001f; 
     //p_viewer.p.alt -= 0.00001f; 
     d = 20000; 
     while(d--); 
    } 
    return 1; 
} 

compute_3d_transform의 코드는 다음과 같습니다 결과에 대한

void compute_3d_transform(struct WorldCamera *p_viewer, struct Point3D_LLA *p_subj, struct Point2D_CalcRes *res, float cliph) 
{ 
    // Estimate the distance to the waypoint. This isn't intended to replace 
    // proper lat/lon distance algorithms, but provides a general indication 
    // of how far away our subject is from the camera. It works accurately for 
    // short distances of less than 1km, but doesn't give distances in any 
    // meaningful unit (lat/lon distance?) 
    res->est_dist = hypot2(p_viewer->p.lat - p_subj->lat, p_viewer->p.lon - p_subj->lon); 
    // Save precious cycles if outside of visible world. 
    if(res->est_dist > cliph) 
     goto quick_exit; 
    // Compute the horizontal angle to the point. 
    // atan2(y,x) so atan2(lon,lat) and not atan2(lat,lon)! 
    res->h_angle = RAD2DEG(angle_dist(atan2(p_viewer->p.lon - p_subj->lon, p_viewer->p.lat - p_subj->lat), p_viewer->yaw)); 
    res->small_dist = res->est_dist * 0.0025f; // by trial and error this works well. 
    // Using the estimated distance and altitude delta we can calculate 
    // the vertical angle. 
    res->v_angle = RAD2DEG(atan2(p_viewer->p.alt - p_subj->alt, res->est_dist)); 
    // Normalize the results to fit in the field of view of the camera if 
    // the point is visible. If they are outside of (0,hfov] or (0,vfov] 
    // then the point is not visible. 
    res->h_angle += p_viewer->hfov/2; 
    res->v_angle += p_viewer->vfov/2; 
    // Set flags. 
    if(res->h_angle < 0 || res->h_angle > p_viewer->hfov) 
     res->flags |= X_OVER; 
    if(res->v_angle < 0 || res->v_angle > p_viewer->vfov) 
     res->flags |= Y_OVER; 
    res->pos.x = (res->h_angle/p_viewer->hfov) * p_viewer->width; 
    res->pos.y = (res->v_angle/p_viewer->vfov) * p_viewer->height; 
    return; 
quick_exit: 
    res->flags |= X_OVER | Y_OVER; 
    return; 
} 

구조 :

typedef struct Point2D_Pixel { unsigned int x, y; }; 

// Structure for storing calculated results (from camera transforms.) 
typedef struct Point2D_CalcRes 
{ 
    struct Point2D_Pixel pos; 
    float h_angle, v_angle, est_dist, small_dist; 
    int flags; 
}; 

코드는 많이 올리는 것은 허용 그래서 내 오픈 소스 프로젝트의 일부입니다 여기에 코드가 있습니다.

+0

'd = 20000; while (d -);'- 이것은 단지 약간의 테스트 일 뿐이라고 생각합니까? – EboMike

+1

"때때로 작동합니다"- 모든 변수를 제대로 초기화하고 있습니까? – EboMike

+0

코드의 어느 부분을 변경하여 실패하게합니까? –

답변

4

일부 계산은 p_viewer->yaw에 따라 다르지만 p_viewer->yaw에 대한 초기화는 표시되지 않습니다. 이게 당신 문제 야?

+0

나는 생각조차하지 못했습니다. 나는 변수 초기화를 생각조차하지 못했고, 결함있는 마이크로를 의심하고있었습니다! 지금 일하고있는 것 같습니다. 문제가 해결 된 것으로 판단되면이 답변을 승인 된 답변으로 표시하겠습니다. 초보자 감사합니다! :) –

1

C를 프로그래밍 할 때이 문제를 해결하기 위해 디버깅 및 정복 디버깅 기술을 사용하여 문제가되는 동작을 격리하려고했습니다. 디버깅 코드가 추가되면서 증상이 변경되는지 여부를 확인합니다. 매달린 포인터 유형 버그).

기본적으로 값이 양호한 첫 번째 줄부터 시작하여 이라는 것이 일관되게 좋습니다. 그런 다음 그것이 나쁜 것으로 알려진 곳을 확인하십시오. 그럼 약. 두 점 사이의 중간에 나쁜지 확인하기위한 테스트를 삽입하십시오. 그렇지 않은 경우 중간 지점과 알려진 불량 위치 사이의 중간에 테스트를 삽입하고 불량 인 경우 중간 지점과 알려진 양호한 위치 사이에 테스트를 삽입하는 식으로 진행합니다.

식별 된 행 자체가 함수 호출이면이 프로세스는 호출 된 함수에서 반복 될 수 있습니다.

이러한 접근 방식을 사용할 때 추가 된 코드의 양과 인공적인 "노이즈"를 최소화하여 타이밍 변경을 유발할 수 있습니다.

대화 형 디버거를 사용하지 않거나 사용할 수없는 경우 또는 사용시 문제가없는 경우이 옵션을 사용하십시오.

2

스케치 보이는 몇 가지 :

  • 당신은 p_res/res의 필드의 여러 설정하지만 발신자가 결코이 문제를 확인하지 않고 compute_3d_transform에서 반환 할 수 있습니다.

  • 먼저 초기화하지 않고 res->flags에서 일관되게 읽습니다.

+0

res-> flag에서 읽는다면 무슨 의미인가요? 나는 단지 비트를 설정하고 있습니다. –

+2

먼저 비트를 지우지 않고 비트를 설정합니다. 'foo | = bar'는 본질적으로'foo = foo | 따라서 당신은 효과적으로 초기화되지 않은 값을 읽는 것입니다. 'res-> flags = 0;'행을'compute_3d_transform'의 맨 근처에 추가 할 수 있습니다. –

1

출력이 다를 때마다 일부 값이 초기화되지 않고 결과가 변수에있는 가비지 값에 따라 달라질 수 있습니다. 이를 염두에두고, 나는 초기화되지 않은 변수를 찾았다. p_res 구조는 초기화되지 않습니다.

if(res->est_dist > cliph) 
     goto quick_exit; 

이는 res-> est_dist에 저장된 가비지 값에 따라 조건이 true 또는 false가 될 수 있음을 의미합니다. 조건이 참이면 true_exit 레이블로 곧바로 이동하고 p_res.pos.x를 업데이트하지 않습니다. 조건이 false로 판명되면 업데이트됩니다.

관련 문제