From: <sv...@ww...> - 2006-04-02 08:04:57
|
Author: mkrose Date: 2006-04-02 00:04:49 -0800 (Sun, 02 Apr 2006) New Revision: 1869 Modified: trunk/csp/csplib/data/LUT.cpp trunk/csp/csplib/data/LUT.h Log: Fix memory corruption in LUT code under GCC 3.4/4.0 related to const reference initialization from temporary objects. Both the bug and the fix are disturbingly subtle, although the impact on the flight model was quite noticeable. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1869 Modified: trunk/csp/csplib/data/LUT.cpp =================================================================== --- trunk/csp/csplib/data/LUT.cpp 2006-04-02 05:57:19 UTC (rev 1868) +++ trunk/csp/csplib/data/LUT.cpp 2006-04-02 08:04:49 UTC (rev 1869) @@ -22,6 +22,7 @@ */ #include <csp/csplib/data/LUT.h> +#include <csp/csplib/util/Log.h> #include <sstream> @@ -29,6 +30,21 @@ CSP_NAMESPACE +// GCC 3.4 and up require a copy constructor for const references to temporaries, +// even if the constructor is optimized away. In fact we want this ctor to always +// be optimized away since the copying the vector elements is expensive. Worse, +// the correct implementation of the copy constructor isn't obvious because of the +// way m_Vp is shared. So we punt and log a fatal error if this ctor is called. +template <int N, typename T> +VEC<N,T>::VEC(VEC const &other): m_Vp(other.m_Vp), m_N(other.m_N) { + CSPLOG(FATAL, NUMERIC) << "VEC copy constructor called\n"; + // best effort implementation, not correct in all cases: + //if (other.m_Vp == other.m_Vec) { + // for (int i = 0; i < m_N; ++i) m_Vec[i] = other.m_Vec[i]; + //} +} + + /** * Second derivative calculation for natural cubic spline * Modified: trunk/csp/csplib/data/LUT.h =================================================================== --- trunk/csp/csplib/data/LUT.h 2006-04-02 05:57:19 UTC (rev 1868) +++ trunk/csp/csplib/data/LUT.h 2006-04-02 08:04:49 UTC (rev 1869) @@ -82,6 +82,11 @@ } } + // GCC 3.4 and up require a copy constructor for const references to temporaries, + // even if the constructor is optimized away. This optimization should occur in + // all cases, so this ctor simply aborts if called. + VEC(VEC const &other); + /** Partial constructor. See operator() for details. */ template <class Y> @@ -448,6 +453,8 @@ public: /** An integer array type for dimensioning the table */ typedef VEC<N, int> Dim; + /** An integer array type for dimensioning a child table */ + typedef VEC<N-1, int> ChildDim; /** A floating point array for specifying table coordinates */ typedef VEC<N, X> Vec; /** An array of breakpoint sets for specifying the input data coordinates */ @@ -508,7 +515,6 @@ return getValue(Vec(x)); } - /** Lookup the value at a given point in the table. * * This method returns a WRAP instance which allows further coordinates to |