c ++ 3d动态数组导致异常

时间:2018-11-12 21:16:01

标签: c++ arrays dynamic heap new-operator

当我尝试通过代码(uint64_t b == 1600)在c ++中创建3d dyn数组时:

uint64_t w = b / 25; // OK

uint32_t ***_3state = new uint32_t**[5]; //OK

for (int i = 0; i < 5; ++i) 
    _3state[i] = new uint32_t*[5]; //OK

for (int i = 0; i < 5; ++i)
    for (int j = 0; j < 5; ++j)
        _3state[i][j] = new uint32_t[w]; //memory access violation

此代码产生运行时内存访问冲突,从而在相应的行中停止执行(由代码中的注释标记)

请帮助我

甚至是单行

new int[w]

将导致运行时异常

如果我从我调用的类中截断了这段代码,然后将其放入main函数中,它将起作用(!)

从main()调用

 char msg[]{ "hello" };
    BitSet b_msg{ msg, 40 };
    State* sha = new State(b_msg);

类状态(为了反映我的目的,我将状态更改为初始状态(_3state更改为_state)):

class State {
    public:
        enum class widthOfPermutation { b0 = 25, b1 = 50, b2 = 100, b3 = 200, b4 = 400, b5 = 800, b6 = 1600 };
        enum class depthOfState { w0 = 1, w1 = 2, w2 = 4, w3 = 8, w4 = 16, w5 = 32, w6 = 64 };
        State(BitSet& s) {
            s = *keccak_c(512, bitset_concat(&s, new BitSet(new UCHAR[1]{ 0x40 }, 2)), 256);
        }
        void toState(BitSet* s, uint64_t b) {
            uint64_t w = b / 25;
            _state = new uint32_t**[5];
            for (int i = 0; i < 5; ++i) 
                _state[i] = new uint32_t*[5];
            for (int i = 0; i < 5; ++i)
                for (int j = 0; j < 5; ++j)
                    _state[i][j] = new uint32_t[w];
            for (int i = 0; i < 5; ++i)
                for (int j = 0; j < 5; ++j)
                    for (int k = 0; k < w; ++k)
                        _state[i][j][k] = s->get_bit(w*(5 * j + i) + k);
        }
        BitSet* toString(uint64_t b) {
            uint64_t w = b / 25;
            BitSet * r = new BitSet(new unsigned char[b / 8], b);
            for (int i = 0; i < 5; ++i)
                for (int j = 0; j < 5; ++j)
                    for (int k = 0; k < w; ++k)
                        r->set_bit(w*(5 * j + i) + k, _state[i][j][k]);
            return r;
        }
        void aTeta(uint64_t b) {
            uint64_t w = b / 25;
            uint32_t ***_state2 = new uint32_t**[5]{ new uint32_t*[5]{ new uint32_t[w] } };
            for (int i = 0; i < 5; ++i)
                for (int j = 0; j < 5; ++j)
                    for (int k = 0; k < w; ++k)
                        _state2[i][j][k] = _state[i][j][k];
            uint32_t** c = new uint32_t*[5]{ new uint32_t[w] };
            for (int i = 0; i < 5; ++i)
                for (int k = 0; k < w; ++k)
                    c[i][k] = _state[i][0][k] ^ _state[i][1][k] ^ _state[i][2][k] ^ _state[i][3][k] ^ _state[i][4][k];
            uint32_t** d = new uint32_t*[5]{ new uint32_t[w] };
            for (int i = 0; i < 5; ++i)
                for (int k = 0; k < w; ++k)
                    d[i][k] = c[mod((i - 1), 5)][k] ^ c[mod((i + 1), 5)][mod((k - 1), w)];
            for (int i = 0; i < 5; ++i)
                for (int j = 0; j < 5; ++j)
                    for (int k = 0; k < w; ++k)
                        _state2[i][j][k] = _state[i][j][k] ^ d[i][k];
            delete[] _state;
            _state = _state2;
        }
        void aRo(uint64_t b) {
            uint64_t w = b / 25;
            uint32_t ***_state2 = new uint32_t**[5]{ new uint32_t*[5]{ new uint32_t[w] } };
            for (int i = 0; i < 5; ++i)
                for (int j = 0; j < 5; ++j)
                    for (int k = 0; k < w; ++k)
                        _state2[i][j][k] = _state[i][j][k];
            uint32_t x = 1, y = 0;
            for (int t = 0; t <= 23; ++t) {
                for (int k = 0; k < w; ++k) {
                    _state2[x][y][k] = _state[x][y][mod((k - (t + 1)*(t + 2) / 2), w)];
                    uint32_t temp = x;
                    x = y;
                    y = mod(2 * temp + 3 * y, 5);
                }
            }
            delete[] _state;
            _state = _state2;
        }
        void aPi(uint64_t b) {
            uint64_t w = b / 25;
            uint32_t ***_state2 = new uint32_t**[5]{ new uint32_t*[5]{ new uint32_t[w] } };
            for (int i = 0; i < 5; ++i)
                for (int j = 0; j < 5; ++j)
                    for (int k = 0; k < w; ++k)
                        _state2[i][j][k] = _state[i][j][k];
            for (int i = 0; i < 5; ++i)
                for (int j = 0; j < 5; ++j)
                    for (int k = 0; k < w; ++k)
                        _state2[i][j][k] = _state[mod(i + 3 * j, 5)][i][k];
            delete[] _state;
            _state = _state2;
        }
        void aXi(uint64_t b) {
            uint64_t w = b / 25;
            uint32_t ***_state2 = new uint32_t**[5]{ new uint32_t*[5]{ new uint32_t[w] } };
            for (int i = 0; i < 5; ++i)
                for (int j = 0; j < 5; ++j)
                    for (int k = 0; k < w; ++k)
                        _state2[i][j][k] = _state[i][j][k];
            for (int i = 0; i < 5; ++i)
                for (int j = 0; j < 5; ++j)
                    for (int k = 0; k < w; ++k)
                        _state2[i][j][k] = _state[i][j][k] ^
                        (_state[mod(i + 1, 5)][j][k] ^ 1) * _state[mod(i + 2, 5)][j][k];
            delete[] _state;
            _state = _state2;
        }
        uint32_t rc(uint64_t t) {
            if (mod(t, 255) == 0) return 1;
            uint32_t intSize = 8;
            uint32_t* r = new uint32_t[intSize];
            r[0] = 1;
            for (int j = 0; j < intSize; ++j) r[j] = 0;
            for (int i = 1; i <= mod(t, 255); ++i) {
                ++intSize;
                uint32_t* temp = new uint32_t[intSize];
                temp[0] = 0;
                for (int j = 1; j < intSize; ++j) {
                    temp[j] = r[j - 1];
                }
                delete[] r;
                r = temp;
                r[0] = (r[0] ^ r[8]) & 0x1;
                r[4] = (r[4] ^ r[8]) & 0x1;
                r[5] = (r[5] ^ r[8]) & 0x1;
                r[6] = (r[6] ^ r[8]) & 0x1;
                --intSize;
            }
            uint32_t res = r[0];
            delete[] r;
            return res;
        }
        void aI(uint64_t b, uint64_t ir) {
            uint64_t w = b / 25;
            uint32_t ***_state2 = new uint32_t**[5]{ new uint32_t*[5]{ new uint32_t[w] } };
            for (int i = 0; i < 5; ++i)
                for (int j = 0; j < 5; ++j)
                    for (int k = 0; k < w; ++k)
                        _state2[i][j][k] = _state[i][j][k];
            uint32_t* RC = new uint32_t[w];
            for (int i = 0; i < w; ++i) RC = 0;
            for (int j = 0; j <= uint64_t(log2(w)); ++j)
                RC[uint64_t(pow(2, j) - 1)] = rc(j + 7 * ir);
            for (int k = 0; k < w; ++k)
                _state2[0][0][k] = _state2[0][0][k] ^ RC[k];
            delete[] _state;
            _state = _state2;
        }
        void rnd(uint64_t b, uint64_t ir) {
            aTeta(b);
            aRo(b);
            aPi(b);
            aXi(b);
            aI(b, ir);
        }
        BitSet* keccak_p(BitSet* s, uint64_t b, uint64_t nr) {
            uint64_t w = s->size_in_bits() / 25;
            uint64_t l = (uint64_t)log2(w);
            toState(s, s->size_in_bits());
            for (int ir = 12 + 2 * l - nr; ir <= 12 + 2 * l - 1; ++ir)
                rnd(b, ir);
            return toString(b);
        }
        BitSet* keccak_f(BitSet* s, uint64_t b) {
            uint64_t w = s->size_in_bits() / 25;
            uint64_t l = (uint64_t)log2(w);
            return keccak_p(s, b, 12 + 2 * l);
        }
        BitSet* sponge(uint64_t b, uint64_t nr,
            uint64_t r,
            BitSet* N,
            uint64_t d) {
            BitSet* p = bitset_concat(N, pad10_1(r, N->size_in_bits()));
            uint64_t n = p->size_in_bits() / r;
            uint64_t c = b - r;
            BitSet ** p_strings = new BitSet*[n] {new BitSet(new UCHAR[r / 8], r)};
            for (int i = 0; i < n; ++i)
                for (int j = 0; j < r; ++j)
                    p_strings[i]->set_bit(j, (p->get_bit(i*r + j)));
            BitSet* s = o(b);
            for (int i = 0; i < n; ++i)
                s = keccak_p(bitset_xor(s, bitset_concat(p_strings[i], o(c))), b, nr);
            BitSet* z = new BitSet();
            while (true) {
                s->trunc(r);
                z = bitset_concat(z, s);
                if (d <= z->size_in_bits()) {
                    z->trunc(d);
                    return z;
                }
                s = keccak_p(s, b, nr);
            }
        }
        BitSet* pad10_1(uint64_t x, uint64_t m) {
            uint64_t j = mod(-int64_t(m) - 2, x);
            return bitset_concat(bitset_concat(new BitSet(new UCHAR[1]{ 0x80 }, 1), o(j)), new BitSet(new UCHAR[1]{ 0x80 }, 1));
        }
        BitSet* keccak_c(uint64_t c, BitSet* N, uint64_t d) {
            return sponge(1600, 24, 1600 - c, N, d);
        }
        ~State() {
            delete[] _state;
        }
    private:
        uint32_t * ** _state;
    };

和BitSet类:

BitSet* o(uint64_t s) { // get ptr to string of 0
        BitSet* r = new BitSet(new unsigned char[s / 8], s);
        for (int i = 0; i < s / 8; ++i)
            r->set_byte(i, 0);
        return r;
    }
    BitSet* bitset_xor(BitSet* x, BitSet* y) {
        uint64_t s = x->size_in_bits();
        BitSet* r = new BitSet(new unsigned char[s/8], s);
        for (int i = 0; i < s; ++i)
            r->set_byte(i, x->get_byte(i) ^ y->get_byte(i));
        return r;
    }
    BitSet* bitset_concat(BitSet* x, BitSet* y) {
        uint64_t s_x = x->size_in_bits();
        uint64_t s_y = y->size_in_bits();
        uint64_t s_r = s_x + s_y;
        BitSet* r = new BitSet(new unsigned char[s_r % 8 ? s_r / 8 + 1 : s_r / 8], s_r);
        int i_r = 0;
        for (int i_x = 0; i_x < s_x; ++i_x, ++i_r)
            r->set_bit(i_r, x->get_bit(i_x));
        --i_r;
        for (int i_y = 0; i_y < s_y; ++i_y, ++i_r)
            r->set_bit(i_r, y->get_bit(i_y));
        return r;
    }
    int64_t round_up(double x) { return x - int64_t(x) ? int64_t(x) + 1 : x; }
    uint64_t mod(int64_t m, int64_t n) {
        return  (m % n + n) % n;
    }
class BitSet { // bit string
public:
    BitSet() { };
    BitSet(void* byte_string, uint64_t size_in_bits)
        : _size_in_bits{ size_in_bits }, _string{ byte_string } { };

    void set_bit(uint64_t index, uint32_t value) {
        reinterpret_cast<unsigned char*>(_string)[index / 8] = value ?
            reinterpret_cast<unsigned char*>(_string)[index / 8] | (unsigned char(0x80) >> (index % 8)) :
            reinterpret_cast<unsigned char*>(_string)[index / 8] & ((unsigned char(0x80) >> (index % 8)) ^ 0xff);
    }
    uint32_t get_bit(uint64_t index) const {
        return reinterpret_cast<unsigned char*>(_string)[index / 8] & unsigned char(0x80) >> (index % 8) ? 1 : 0;
    }

    void set_byte(uint64_t index, unsigned char value) {
        reinterpret_cast<unsigned char*>(_string)[index] = value;
    }
    unsigned char get_byte(uint64_t index) {
        return reinterpret_cast<unsigned char*>(_string)[index];
    }

    void trunc(uint64_t s) {
        _size_in_bits = s;
    }
    void reapply(void* byte_string, uint64_t size_in_bits) {
        _string = byte_string;
        _size_in_bits = size_in_bits;
    }
    void* string_ptr() { return _string; }

    uint64_t size_in_bytes() const { 
        return _size_in_bits%8 ? _size_in_bits/8 + 1 : _size_in_bits / 8; }
    uint64_t size_in_bits() const { return _size_in_bits; }

private:
    void* _string = nullptr;
    uint64_t _size_in_bits = 0;
};

1 个答案:

答案 0 :(得分:0)

您可以创建一维数组并将其用作3维数组,而不是创建“指向指针的指针”数组,将3个索引转换为1。

const size_t SIZE_X = 5;
const size_t SIZE_Y = 5;
const size_t SIZE_Z = 5;

uint32_t *array_1d = new uint32_t[SIZE_X * SIZE_Y * SIZE_Z];

// returns reference to element in 1-d array as if it was 3-d
uint32_t& get_element(size_t x, size_t y, size_t z) {
  const size_t ind = x * SIZE_Y * SIZE_Z + y * SIZE_Z + z;
  return array_1d[ind];
}

用法:

// set
get_element(0, 3, 2) = 5;
// get
cout << get_element(3, 1, 1);