2010-11-29 12 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つのポイントの中間にテストを挿入して、悪いかどうかを確認します。そうでない場合は、中点と既知の不良位置の中間にテストを挿入し、不良であれば中点と既知の良好な位置の中間にテストを挿入します。

識別された行自体が関数呼び出しである場合、このプロセスは呼び出された関数などで繰り返されます。

このようなアプローチを使用する場合は、追加されるコードの量と人為的な「ノイズ」を最小限に抑えてタイミングの変化を招くことが重要です。

対話型デバッガを使用していない(または使用できない)場合、または使用時に問題が発生しない場合は、これを使用します。

2

大ざっぱに見える物事のカップル:

  • あなたはp_res/resのフィールドの多くは設定せずにcompute_3d_transformから戻ることができますが、呼び出し側は、このような状況をチェックすることはありません。

  • res->flagsから一貫して読み込みます。最初に初期化する必要はありません。

+0

あなたがres-> flagsから読んだとすると、どういう意味ですか?私はちょうどビットを設定しています。 –

+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になると、すぐにquick_exitラベルに進み、p_res.pos.xを更新しません。条件がfalseであると判明した場合、その条件は更新されます。

関連する問題