2016-12-06 82 views
-1

我有一个具有以下功能的复杂的代码(有些算法很可能是错误的,但它的技术方面的问题):复制失败(分段错误)

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行,运算符%就是正确的代码,并且在我的具体case正确调用else语句(具体地说,对rval变量的赋值很好,即使正确计算了内容。不过,我假设实际返回变量rval的副本。但是,该变量未在相关语句中分配给q。 Valgrind的返回

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基本上是一个数组复制。 有关我如何调试问题的任何线索?我真的不知道该看什么。

更新:运营商=

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

更新2:

功能set_ui_const

void set_ui_const(uint64_t* y,const uint64_t* x, int ny, int nx) 
{ 
    assert(nx >= 1 && ny >= 1); 

    int Nx, Ny, Nmin, j, n2y; 

    Nx = (nx + 63)/64; 
    Ny = (ny + 63)/64; 
    n2y = (ny - (Ny-1)*64); 
    Nmin = (Nx <= Ny) ? Nx : Ny; 

    for (j = 0; j <= Nmin - 1; j++) 
     y[j] = x[j]; 
    for (j = Nmin; j <= Ny - 1; j++) 
     y[j] = 0ULL; 

    if (n2y != 64) { 
     y[Ny - 1] &= (1ULL << n2y) - 1ULL; 
    } 
} 
+0

您可以请*显示*我们的'set_ui_const'功能?另外,当'L'等于'75'(好像是),那么请记住'(75 + 63)/ 64'在'2.2'附近,你的数组只有'2'个元素大。你会只复制两个元素?或者更多? –

+0

基本上它会停止复制第一个元素(所以索引为'0')。但我相信尺寸很好。 – user8469759

+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: ??? 

通常意味着你在某处存在堆栈缓冲区溢出。请注意,在ASCII的“返回”地址0x373635343332312F拼写"/1234567"(不含引号)。

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

+0

由于我正在使用静态编译,因此'fsanitaze'不起作用。你突出显示的行是什么意思? '0x4012D7'它读取单元格[[0]'处的第二个参数。我有分段故障的地方。我知道分段错误何时发生,但我不明白为什么。我不能使用valgrind来执行更准确的分析吗?你能告诉我如何? – user8469759

+0

@ user8469759你的程序中的任何地方是否有字符串'/ 1234567'?在该计划的输入?然后,您需要查看该字符串的处理位置,并确保为该字符串分配了足够的内存。使用'std :: string'是一个很好的开始。或其他[标准容器](http://en.cppreference.com/w/cpp/container)。在C++中,大多数情况下可以避免使用指针和动态内存处理,但我建议您尝试重构代码,除非绝对需要(调用C函数,多态性),否则不要使用指针。 –

+0

@雇用俄罗斯人,根本不使用这样的字符串。没有使用这种类型的输入。没有使用dynanic分配或释放。 – user8469759