调试语句放置修复的不一致输出

时间:2012-03-12 20:05:55

标签: c++

编辑:这是一个未初始化的变量...... :(

说明: 我使用的PointLLA构造函数只通过Latitude和Longitude,但我从未明确将内部Altitude成员变量设置为0. Rookie错误......

原始问题: 我的代码中有一个错误,我有一段非常可怕的时间。我正在计算单个点和矩形角之间的距离。在这种情况下,该点以矩形为中心,因此我应该得到四个相等的距离。我得到三个相等的距离,一个几乎相等的距离值是不一致的(每次运行都不同)。

如果我有几个关键的调试语句(几乎只是一个std :: cout调用)明确打印出每个矩形角的位置,我得到距离的预期值,并且不一致性消失。这是相关的代码:

// calculate the minimum and maximum distance to
// camEye within the available lat/lon bounds
Vec3 viewBoundsNE;   convLLAToECEF(PointLLA(maxLat,maxLon),viewBoundsNE);
Vec3 viewBoundsNW;   convLLAToECEF(PointLLA(maxLat,minLon),viewBoundsNW);
Vec3 viewBoundsSW;   convLLAToECEF(PointLLA(minLat,minLon),viewBoundsSW);
Vec3 viewBoundsSE;   convLLAToECEF(PointLLA(minLat,maxLon),viewBoundsSE);

// begin comment this block out, and buggy output
OSRDEBUG << "INFO: NE (" << viewBoundsNE.x
         << "  " << viewBoundsNE.y
         << "  " << viewBoundsNE.z << ")";
OSRDEBUG << "INFO: NW (" << viewBoundsNW.x
         << "  " << viewBoundsNW.y
         << "  " << viewBoundsNW.z << ")";
OSRDEBUG << "INFO: SE (" << viewBoundsSW.x
         << "  " << viewBoundsSW.y
         << "  " << viewBoundsSW.z << ")";
OSRDEBUG << "INFO: SW (" << viewBoundsSE.x
         << "  " << viewBoundsSE.y
         << "  " << viewBoundsSE.z << ")";
// --------------- end

// to get the maximum distance, find the maxima
// of the distances to each corner of the bounding box
double distToNE = camEye.DistanceTo(viewBoundsNE);
double distToNW = camEye.DistanceTo(viewBoundsNW); // <-- inconsistent
double distToSE = camEye.DistanceTo(viewBoundsSE);
double distToSW = camEye.DistanceTo(viewBoundsSW);

std::cout << "INFO: distToNE: " << distToNE << std::endl;
std::cout << "INFO: distToNW: " << distToNW << std::endl; // <-- inconsistent
std::cout << "INFO: distToSE: " << distToSE << std::endl;
std::cout << "INFO: distToSW: " << distToSW << std::endl;

double maxDistToViewBounds = distToNE;

if(distToNW > maxDistToViewBounds)
{   maxDistToViewBounds = distToNW;   }

if(distToSE > maxDistToViewBounds)
{   maxDistToViewBounds = distToSE;   }

if(distToSW > maxDistToViewBounds)
{   maxDistToViewBounds = distToSW;   }

OSRDEBUG << "INFO: maxDistToViewBounds: " << maxDistToViewBounds;

因此,如果我运行上面显示的代码,我将得到如下输出:

INFO: NE (6378137  104.12492  78.289415)
INFO: NW (6378137  -104.12492  78.289415)
INFO: SE (6378137  -104.12492  -78.289415)
INFO: SW (6378137  104.12492  -78.289415)
INFO: distToNE: 462.71851
INFO: distToNW: 462.71851
INFO: distToSE: 462.71851
INFO: distToSW: 462.71851
INFO: maxDistToViewBounds: 462.71851

完全符合预期。请注意,所有distTo *值都相同。我可以一遍又一遍地运行程序,我会得到完全相同的输出。但是现在,如果我在上面的代码中注释掉我注意到的块,我会得到类似的结果:

INFO: distToNE: 462.71851
INFO: distToNW: 463.85601
INFO: distToSE: 462.71851
INFO: distToSW: 462.71851
INFO: maxDistToViewBounds: 463.85601

每次运行都会稍微改变一下。为什么要分散而不是其他价值?我不知道。再运行几次:

463.06218
462.79352
462.76194
462.74772
463.09787
464.04648

那么......这里发生了什么?我尝试清理/重建我的项目,看看是否有一些奇怪的事情发生但它没有帮助。我正在使用GCC 4.6.3和x86目标。

编辑:添加相关功能的定义。

void MapRenderer::convLLAToECEF(const PointLLA &pointLLA, Vec3 &pointECEF)
{
    // conversion formula from...
    // hxxp://www.microem.ru/pages/u_blox/tech/dataconvert/GPS.G1-X-00006.pdf

    // remember to convert deg->rad
    double sinLat = sin(pointLLA.lat * K_PI/180.0f);
    double sinLon = sin(pointLLA.lon * K_PI/180.0f);
    double cosLat = cos(pointLLA.lat * K_PI/180.0f);
    double cosLon = cos(pointLLA.lon * K_PI/180.0f);

    // v = radius of curvature (meters)
    double v = ELL_SEMI_MAJOR / (sqrt(1-(ELL_ECC_EXP2*sinLat*sinLat)));
    pointECEF.x = (v + pointLLA.alt) * cosLat * cosLon;
    pointECEF.y = (v + pointLLA.alt) * cosLat * sinLon;
    pointECEF.z = ((1-ELL_ECC_EXP2)*v + pointLLA.alt)*sinLat;
}

    // and from the Vec3 class defn
    inline double DistanceTo(Vec3 const &otherVec) const
    {
        return sqrt((x-otherVec.x)*(x-otherVec.x) +
                    (y-otherVec.y)*(y-otherVec.y) +
                    (z-otherVec.z)*(z-otherVec.z));
    }

4 个答案:

答案 0 :(得分:5)

不一致的输出表明您在代码中的某处使用了未初始化的变量,或者您有一些内存错误(访问已删除的内存,双重删除内存等)。我没有看到你粘贴的代码中发生过这些事情,但是还有许多其他代码被调用。

Vec3构造函数是否将所有成员变量初始化为零(或某些已知状态)?如果没有,那么这样做,看看是否有帮助。如果它们已经初始化,请仔细查看convLLAToECEF和PointLLA以查看是否有任何变量未初始化或者是否存在任何内存错误。

答案 1 :(得分:0)

在我看来,DistanceTo函数在某种程度上被窃听。如果你无法解决问题,请尝试一下,并报告回来。

  • 尝试重新排序输出以查看它是否仍然是NW错误。
  • 尝试将NW点重复2-3次到不同的变量中,看它们在一次运行中是否一致。
  • 尝试为每个点使用不同的camEye来排除该类中的有状态。

答案 2 :(得分:0)

尽管我讨厌它,你是否在调试器中逐步完成了它?我通常倾向于基于stdout的调试,但似乎它有所帮助。除此之外,你有一些令人讨厌的踢腿的副作用。

我的猜测是,你希望(当然正确地)所有四个值相同的事实是在某处掩盖“NW / SW / NE / SE”错字。我要做的第一件事是将你在这里拥有的块隔离到它自己的函数(它采用框和点坐标),然后用几个不同位置的点运行它。我认为这个错误很可能会在那时迅速暴露出来。

答案 3 :(得分:0)

如果您有调试语句,请查看问题是否重现,但在输出后移动它们。然后,调试语句可以帮助确定是Vec3对象是否已损坏,或者是从中进行计算。

其他想法:在valgrind下运行代码。

分解反汇编输出。