使用重载运算符后复制失败(分段错误)

时间:2016-12-06 11:51:55

标签: c++ templates segmentation-fault gdb valgrind

我有一个复杂的代码,具有以下功能(某些算法可能不对,但问题是技术方面):

template<int L>
string toStringBase(const StaticUnsigned<L>& x, int base) { //between {2,...,16}
   assert(2 <= base && base <= 16);
   StaticUnsigned<L> t, q, _base, _base_to_n;
   _base = (uint64_t)base;
   t = x;
   q = t;
   string str = "";
   _base_to_n = 1LL;
   char digits[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
   while(t > StaticUnsigned<L>(0ULL)) { 
      q = t % _base; //The problem is here!
      std::cout << "Partial conversion = " << str << std::endl;
      str += digits[q.mem[0]];
      t = t / _base; //right shift
   }
   return str;
}

%运算符重载如下:

template<int L>
template<int M>
inline StaticUnsigned<MaxInt<L, M>::value> StaticUnsigned<L>::operator %(
   const StaticUnsigned<M>& _m) const
{
   StaticUnsigned<MaxInt<L, M>::value> rval, x, y;
   x = *this;
   y = _m;
   if (y > x) {
      return x;
   } else {
      rval = x / y;
      rval = x - rval * y;
      return rval;
   }
}

在这个特定情况下,我有如下实现的复制构造函数

template<int L>
inline StaticUnsigned<L>::StaticUnsigned(const StaticUnsigned<L>& _m)
{
   set_ui_const(this->mem, _m.mem, L, L);
}

现在......接下来会发生什么(来自gdb)......我基本上调用了函数toStringBase,并且一旦到达行q = t % base就调用了相关的函数{ {1}}是正确的代码,在我的特定情况下,%语句被正确调用(特别是对else变量的赋值很好,即使内容被正确计算。但是我假设一个副本实际返回变量rval。然而,此变量未在相关语句中分配给rval .Valgrind返回

q

地址:0000000000000000 000000000000000a ==5613== Invalid read of size 8 ==5613== at 0x4012D7: set_ui_const(unsigned long*, unsigned long const*, int, int) (basic.cc:320) ==5613== by 0x404C9B: StaticUnsigned<75>::operator=(StaticUnsigned<75> const&) (static_unsigned.h:205) ==5613== by 0x404F1D: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > toStringBase<75>(StaticUnsigned<75> const&, int) (static_unsigned.h:453) ==5613== by 0x373635343332312F: ??? ==5613== by 0x23B3A3937: ??? ==5613== by 0x7FEFFEFCF: ??? ==5613== by 0x7FEFFF04F: ??? ==5613== by 0x373635343332312F: ??? ==5613== by 0x4645444342413937: ??? ==5613== Address 0xffffffffffffffd0 is not stack'd, malloc'd or (recently) free'd ==5613== ==5613== ==5613== Process terminating with default action of signal 11 (SIGSEGV) ==5613== Access not within mapped region at address 0xFFFFFFFFFFFFFFD0 ==5613== at 0x4012D7: set_ui_const(unsigned long*, unsigned long const*, int, int) (basic.cc:320) ==5613== by 0x404C9B: StaticUnsigned<75>::operator=(StaticUnsigned<75> const&) (static_unsigned.h:205) ==5613== by 0x404F1D: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > toStringBase<75>(StaticUnsigned<75> const&, int) (static_unsigned.h:453) ==5613== by 0x373635343332312F: ??? ==5613== by 0x23B3A3937: ??? ==5613== by 0x7FEFFEFCF: ??? ==5613== by 0x7FEFFF04F: ??? ==5613== by 0x373635343332312F: ??? ==5613== by 0x4645444342413937: ??? ==5613== If you believe this happened as a result of a stack ==5613== overflow in your program's main thread (unlikely but ==5613== possible), you can try to increase the size of the ==5613== main thread stack using the --main-stacksize= flag. ==5613== The main thread stack size used in this run was 10485760. ==5613== 应该是返回的0xffffffffffffffd0副本的地址。但我不明白为什么,复制构造函数应该没问题。

顺便提一下rval类看起来像(只是一个划痕,并不是所有的方法都报告过):

StaticUnsigned

template<int L> class StaticUnsigned { public: StaticUnsigned(); //ok template<int M> StaticUnsigned(const StaticUnsigned<M>& _m); StaticUnsigned(const StaticUnsigned<L>& _m); //ok template<int M = 64> //ok StaticUnsigned<MaxInt<L, M>::value> operator%( const StaticUnsigned<M>& _m) const; template<int M = 64> StaticUnsigned<L>& operator=(const StaticUnsigned<M>& _m); //ok StaticUnsigned<L>& operator=(const StaticUnsigned<L>& _m); //ok public: uint64_t mem[(L + 63) / 64]; }; 基本上是一个数组复制。 关于如何调试问题的任何线索?我真的不知道该看什么。

更新:运营商set_ui_const

=

更新2:

函数template<int L> template<int M> inline StaticUnsigned<L>& StaticUnsigned<L>::operator =( const StaticUnsigned<M>& _m) { if (this != (StaticUnsigned<L>*) (&_m)) { StaticUnsigned<M> tmp = _m; set_ui(this->mem, tmp.mem, L, M); } return *this; } template<int L> inline StaticUnsigned<L>& StaticUnsigned<L>::operator =( const StaticUnsigned<L>& _m) { if (this != &_m) { set_ui_const(this->mem, _m.mem, L, L); } return *this; }

set_ui_const

1 个答案:

答案 0 :(得分:0)

此:

==5613== Invalid read of size 8
==5613==    at 0x4012D7: set_ui_const(unsigned long*, unsigned long const*, int, int) (basic.cc:320)
==5613==    by 0x404C9B: StaticUnsigned<75>::operator=(StaticUnsigned<75> const&) (static_unsigned.h:205)
==5613==    by 0x404F1D: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > toStringBase<75>(StaticUnsigned<75> const&, int) (static_unsigned.h:453)
==5613==    by 0x373635343332312F: ???

通常表示您在某处有堆栈缓冲区溢出。请注意0x373635343332312F中的“返回”地址"/1234567"拼写ASCII(不带引号)。

调试此类问题的最佳方法是使用Address Sanitizer,最近版本的GCC和Clang支持-fsanitize=address标记。