间歇性错误 - 有时这段代码有效,有时则不行!

时间:2010-11-29 22:09:10

标签: c

此代码间歇性地工作。它在一个小型微控制器上运行。即使重新启动处理器,它也能正常工作,但是如果我更改了部分代码,它就会中断。这让我觉得它是某种指针错误或内存损坏。发生的是坐标,p_res.pos.x有时读取为0(不正确的值)和96(正确的值)传递给write_circle_outlined。在大多数情况下,似乎是正确的。如果有人能发现任何明显错误的信息,请指出来!

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

代码是我的开源项目的一部分,因此可以在这里发布大量代码。

4 个答案:

答案 0 :(得分:4)

我看到你的一些计算取决于p_viewer->yaw,但我没有看到p_viewer->yaw的任何初始化。这是你的问题吗?

答案 1 :(得分:2)

一些看似粗略的事情:

  • 您可以从compute_3d_transform返回,而无需设置p_res / res中的多个字段,但来电者从不检查此情况。

  • 您始终从res->flags读取而不先将其初始化。

答案 2 :(得分:1)

当我用C程序中,我会用一个分而治之为这类问题调试技术来尝试隔离有问题的操作(注意症状是否改变,因为加入调试代码,其指示悬空的指针类型错误)。

基本上,开始与其中值是已知的良好的第一行(和证明它的在该行一贯良好)。然后确定它在哪里是坏的。然后约。在两点之间插入一个测试,看看它是不是很糟糕。如果不是,然后将中间点和已知不良位置之间的测试半途而废,如果它是坏的,然后插入中间点和已知良好的位置之间的中途测试,等等。

如果识别的行本身是一个函数调用,则可以在该被调用的函数中重复此过程,依此类推。

使用这种方法时,最大限度地减少添加的代码量和人为的“噪音”非常重要,这可能会造成时间变化。

如果您没有(或不能使用)交互式调试器,或者在使用交互式调试器时没有显示问题,请使用此项。

答案 3 :(得分:1)

每当输出不同时,它可能意味着某些值未初始化,结果取决于变量中存在的垃圾值。牢记这一点,我寻找未初始化的变量。结构p_res未初始化。

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

这意味着条件可能会变为真或假,具体取决于res-&gt; est_dist中存储的垃圾值。当if条件变为true时,它直接转到quick_exit标签并且不更新p_res.pos.x。如果条件结果为假,则更新。