2010-11-29 80 views
0

此代碼間歇性地工作。它運行在一個小型微控制器上。即使在重新啓動處理器後,它也能正常工作,但是如果我更改了代碼的一部分,它就會中斷。這讓我認爲這是某種指針錯誤或內存損壞。發生的是座標,當它傳遞給write_circle_outlined時,p_res.pos.x有時被讀爲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;而(d - );` - 我希望這只是一個小測試? – EboMike 2010-11-29 22:14:04

+1

至於「有時候工作」 - 你是否正確初始化所有變量? – EboMike 2010-11-29 22:14:38

+0

你改變了哪部分代碼,導致它失敗? – 2010-11-29 22:17:43

回答

4

我看到你的一些計算取決於p_viewer->yaw,但我沒有看到p_viewer->yaw的任何初始化。這是你的問題嗎?

1

當我用C編寫程序時,我會使用分而治之的調試技術來解決這類問題,以嘗試隔離有問題的操作(注意症狀是否隨着調試代碼的添加而改變,這表示懸掛指針類型錯誤)。

本質上,從第一行開始,其中值已知是好的(並且證明它始終在該行中良好)。然後確定哪裏是壞的。然後約。在兩點之間的中間插入一個測試,看看它是否壞。如果不是,則在中點和已知不良位置之間的中間插入測試,如果不合適,則在中點和已知良好位置之間的中間插入測試,依此類推。

如果標識的行本身是一個函數調用,則可以在該調用的函數中重複該過程,依此類推。

當使用這種方法時,重要的是儘量減少添加的代碼量和人爲的「噪聲」,這可能會產生時序變化。

如果您沒有(或不能使用)交互式調試器,或者在使用交互式調試器時未出現問題,請使用此選項。

2

一對夫婦的事情,似乎粗略:

  • 您可以從compute_3d_transform返回沒有設置許多領域的p_res/res但主叫方從來沒有檢查這種情況。

  • 您始終從res->flags開始讀取,而無需先初始化。

1

只要輸出不同,可能意味着某些值未初始化,結果取決於變量中存在的垃圾值。牢記這一點,我尋找未初始化的變量。結構p_res未被初始化。

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

這意味着如果條件可能會變成真或假,這取決於res-> est_dist中存儲的垃圾值。如果條件變爲true,則會直接轉到quick_exit標籤並且不會更新p_res.pos.x。如果條件結果是錯誤的,那麼它的更新。

相關問題