通过调试语句放置修复了不一致的输出
inconsistent output fixed by debug statement placement
EDIT:这是一个未初始化的变量…:(
说明:我使用的PointLLA构造函数只通过Latitude和Longitude,但我从未明确将内部Altitude成员变量设置为0。新手失误。。。
原始问题:我的代码中出现了一个错误,这让我很难过。我在计算一个点和一个矩形的角之间的距离。在这种情况下,点位于矩形的中心,所以我应该得到四个相等的距离。我得到三个相等的距离,还有一个几乎相等的不一致的距离值(每次运行都不同)。
如果我有几个关键的调试语句(几乎只是一个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
每次跑步的distToNW略有不同。为什么distToNW而不是其他值?我不知道。再跑几次:
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));
}
不一致的输出表明您正在使用代码中某个未初始化的变量,或者您有一些内存错误(访问已删除的内存、双重删除内存等)。我在您粘贴的代码中没有看到这两种情况,但还有很多其他代码被调用。
Vec3构造函数是否将所有成员变量初始化为零(或某些已知状态)?如果没有,那么就这样做,看看这是否有帮助。如果它们已经初始化,请仔细查看convlAToECEF和PointLLA,看看是否有任何变量没有初始化,或者是否有任何内存错误。
在我看来,DistanceTo
函数在某种程度上被窃听了。如果你不能弄清楚发生了什么,那就试一下,然后汇报。
- 尝试重新排序输出,看看是否仍然是NW错误
- 试着把NW点重做2-3次,变成不同的变量,看看它们在一次跑步中是否一致
- 尝试对每个点使用不同的
camEye
来排除该类中的状态性
尽管我很讨厌它,但你在调试器中经历过吗?我通常倾向于基于stdout的调试,但这似乎会有所帮助。除此之外,你也会因为一些讨厌的事情而产生副作用。
我的猜测是,事实上,你期望(当然是正确的)所有四个值都是相同的,这掩盖了某个地方的"NW/SW/NE/SE"拼写错误。我要做的第一件事是将你在这里得到的块隔离到它自己的函数中(获取框和点坐标),然后在几个不同的位置使用点运行它。我认为这个错误很可能会很快暴露出来。
如果您有调试语句,但在输出之后移动它们,则查看问题是否会再次出现。然后,调试语句可以帮助确定是Vec3
对象损坏了,还是来自它的计算
其他想法:在valgrind
下运行代码。
仔细检查拆卸输出。
- 大于65535的C++数组[size]引发不一致的溢出
- 为什么在C的循环中使用printf的Rust代码不显示输出,而在C++的循环中显示std::cout
- 在 C++(和 C)中进行类型转换时明显不一致
- 填充上编译器生成的复制构造函数之间的不一致
- 犰狳的 print() 方法和 cout 在从 Rcpp 调用时顺序不一致
- CreateDIBSection为同一图像返回不一致的位图位值
- 在 Qml 中从 QSqlTableModel 中删除单行时视图不一致
- 模板参数推导不一致
- 声明中不一致的no是否违反ODR?
- 如何删除分支因子不一致的树,最大为 30,40
- 如何在不丢失输出的情况下杀死/停止终端中正在运行的进程?
- 从 C++ 函数与 Python 函数返回的不一致值用于偏斜正态分布
- 从 C 字符串构造 std::string 与从另一个 std::string 构造 std::string 不一致
- 同时读取和写入时输出不一致
- 二阶多项式计算器的输出不一致
- 创建邻接列表时的输出不一致
- GCC和MSVC之间的文件输出不一致
- 通过调试语句放置修复了不一致的输出
- 我做了什么导致这个程序的输出不一致?
- ofstream不一致地创建/写入输出文件