私は次の関数(いくつかのアルゴリズムは、おそらく間違っているが、それは問題の技術的な側面だ)との複雑なコードがあります:%
オペレータがある過負荷演算子の使用後のコピー(セグメンテーションフォールトを)失敗し
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
に到達すると、演算子%
は適切にコードされています。その場合、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
のコピーのアドレスであると考えられます。しかし、なぜコピーコンストラクタがうまくいくのか理解できません。
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
は、基本的には、配列のコピーである:(ちょうどスクラッチ、すべてのメソッドが報告されていない)のようなクラスStaticUnsigned
に見えるところで
。 問題をデバッグする方法についての手がかりはありますか?私は本当に何を見るべきか分からない。
更新:オペレータ=
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;
}
}
'set_ui_const'関数を*表示*できますか?また、 'L'が' 75'(それがそうであるように)で '(75 + 63)/ 64'が' 2.2'の周りにあることを覚えていれば、あなたの配列は '2'要素だけです。 2つの要素だけをコピーしますか?以上? –
基本的に、最初の要素(インデックス '0'を持つ要素)をコピーするのを止めます。しかし、私はサイズが良いと確信しています。 – user8469759
ちなみに、コピーコンストラクタの代わりに代入演算子を表示するべきでしょう。これは、コールスタックに応じて問題につながっているようです。 –