分段错误(核心转储)动态阵列

Segmentation fault (core dumped) Dynamic Array

本文关键字:动态 阵列 转储 核心 错误 分段      更新时间:2023-10-16

>我收到以下代码的分段错误:

这是标题:

using namespace std;
class Dynamic_array {
public:
    Dynamic_array();
    Dynamic_array(Dynamic_array &);
    Dynamic_array &operator=(Dynamic_array &);
    ~Dynamic_array();
    void print_state(void);
    int get_size(void);
    int& operator[](int);
    void insert(int, int);
    void insert(Dynamic_array &, int);
    void remove(int);
    void remove(int, int);
    class Subscript_range_exception {
    };
private:
    enum {
        BLOCK_SIZE = 5,
    };
    class Block {
    public:
        int size;
        int a[BLOCK_SIZE];
        Block* next_p;
    };
    class Block_position {
    public:
        Block* block_p;
        Block* pre_block_p;
        int i;
    };
    Block_position find_block(int i);
    void insert_blocks(Block *, Block *);
    void remove_blocks(Block *, Block *, Block *);
    Block * copy_blocks(Block *);
    void delete_blocks(Block *);
    int size;
    Block* head_p;
};

以及我的其余代码。当块的大小为 1 时,它有效。当大小大于 1 时,它会引发分段错误。

#include <iostream>                                     //-
#include <string.h>                                     //-
#include "dynamic_array.h"                                  //-
                                                //-
using namespace std;                                        //-
                                                //-
// ********** public functions **********                           //-
int main(){
    Dynamic_array d;
    d.insert(1,0);
    d.insert(3,1);
    d.insert(5,2);
    d.insert(7,3);
    d.insert(9,4);
    d.insert(11,5);
    d.print_state();
    cout << "********** remove(int i)" << endl;
    cout << "********** case 1: range error" << endl;
    try {
        d.remove(-1);
    } catch (Dynamic_array::Subscript_range_exception) {
        cout << "exception caught at -1" << endl;
    }
    try {
        d.remove(6);
    } catch (Dynamic_array::Subscript_range_exception) {
        cout << "exception caught at 6" << endl;
    }
    cout << "********** case 2: block size == 1" << endl;
    d.remove(5);
    d.print_state();
    cout << "********** case 3: block size > 1" << endl;
    cout << "***** remove right element" << endl;
    d.remove(4);
    d.print_state();
    cout << "***** remove left element" << endl;
    d.remove(0);
    d.print_state();
}
                                                //-
Dynamic_array::Dynamic_array() {                                //-
    head_p = NULL;                                      //-
    size = 0;                                       //-
}                                               //-
                                                //-
Dynamic_array::Dynamic_array(Dynamic_array & d) {                       //-
}                                               //-
                                                //-
Dynamic_array &Dynamic_array::operator=(Dynamic_array & d) {                    //-
    return *this;                                       //-
}                                               //-
                                                //-
Dynamic_array::~Dynamic_array() {                               //-
}                                               //-
                                                //-
void Dynamic_array::print_state(void) {                             //-
    cout << "size:" << size << endl;                            //-
    for (Block * p = head_p; p != NULL; p = p->next_p) {                    //-
        cout << "tsize:" << p->size << " elements:";                   //-
        for (int i = 0; i < p->size; i++) {                     //-
            cout << p->a[i] << ' ';                         //-
        }                                       //-
        cout << endl;                                   //-
    }                                           //-
}                                               //-
                                                //-
int Dynamic_array::get_size(void) {                             //-
    return size;
}                                               //-
                                                //-
int& Dynamic_array::operator[](int i) {                             //-
    // check i for range error                              //-
    if (i < 0 || i >= size) {                               //-
        throw Subscript_range_exception();                      //-
    }                                           //-
                                                //-
    // find target block and index                              //-
    Block_position position = find_block(i);                        //-
                                                //-
    // return element at index i                                //-
    return position.block_p->a[position.i];                         //-
}                                               //-
                                                //-
void Dynamic_array::insert(int x, int i) {                          //-
    // case 1: range error                                  //-
    if (i < 0 || i > size) {                                //-
        throw Subscript_range_exception();                      //-
    }                                           //-
                                                //-
    // case 2: empty array                                  //-
    if (size == 0) {                                    //-
        // create linked list consisting of a single new block              //-
        Block * new_block_p = new Block;                        //-
        new_block_p->size = 1;                              //-
        new_block_p->a[0] = x;                              //-
        new_block_p->next_p = NULL;                         //-
                                                //-
        // insert new block                             //-
        insert_blocks(NULL, new_block_p);                       //-
                                                //-
        // update total size                                //-
        size++;                                     //-
                                                //-
        return;                                     //-
    }                                           //-
                                                //-
    // find target block and index                              //-
    Block_position position = find_block(i);                        //-
                                                //-
    // case 3: non-empty array; new block not needed                    //-
    if (position.block_p->size < BLOCK_SIZE) {                      //-
        // shift block array right                          //-
        for (int j = position.block_p->size; j > position.i; j--) {         //-
            position.block_p->a[j] = position.block_p->a[j-1];          //-
        }                                       //-
                                                //-
        // assign x                                 //-
        position.block_p->a[position.i] = x;                        //-
                                                //-
        // update array and block size                          //-
        size++;                                     //-
        position.block_p->size++;                           //-
                                                //-
    // case 4: non-empty array; new block needed                        //-
    } else {                                        //-
        // create new block                             //-
        Block * new_block_p = new Block;                        //-
        new_block_p->size = 1;                              //-
        new_block_p->next_p = NULL;                         //-
                                                //-
        // case 4.a: insert x into old block                        //-
        if (position.i < BLOCK_SIZE) {                          //-
            // copy last array element to new block                 //-
            new_block_p->a[0] = position.block_p->a[BLOCK_SIZE-1];          //-
                                                //-
            // shift old block array right                      //-
            for (int j = position.block_p->size-1; j > position.i; j--) {       //-
                position.block_p->a[j] = position.block_p->a[j-1];      //-
            }                                   //-
                                                //-
            // assign x into old block                      //-
            position.block_p->a[position.i] = x;                    //-
                                                //-
        // case 4.b: insert x into new block                        //-
        } else {                                    //-
            new_block_p->a[0] = x;                          //-
        }                                       //-
                                                //-
        // update total size                                //-
        size++;                                     //-
                                                //-
        // insert new block into linked list                        //-
        insert_blocks(position.block_p, new_block_p);                   //-
    }                                           //-
}                                               //-
                                                //-
void Dynamic_array::insert(Dynamic_array &p, int i) {                       //-
    // case 1: range error                                  //-
    // case 2: parameter array empty                            //-
    // case 3: array empty                                  //-
    // find target block and index                              //-
    Block_position position = find_block(i);                        //-
    // case 4: array non-empty; new blocks not needed                   //-
    // case 5: array non-empty; new blocks needed                       //-
        // copy p                                   //-
        Block * copy_p = copy_blocks(p.head_p);                     //-
        // case 5.a: insert position at start of block                  //-
        // case 5.b: insert position at middle of block                 //-
        // case 5.c: insert position after end of block                 //-
        // update total size                                //-
}                                               //-
                                                //-
void Dynamic_array::remove(int i) {                             //-
    // case 1: range error                                  //-
    if (i < 0 || i >= get_size()) {                             //-
        throw Subscript_range_exception();                      //-
    }
    Block_position index = find_block(i);
    cout << "Position : " << index.i << endl;
    // find target block and index                              //-
    // case 2: block size == 1                              //-
    if(index.block_p->size == 1) {
        remove_blocks(NULL,index.block_p,index.block_p);
    }
    // case 3: block size > 1                               //-
    else if(index.block_p->size > 1) {
        cout << "made it " << endl;
        for (int j = index.i; j < BLOCK_SIZE-1; ++j){
            index.block_p->a[j] = index.block_p->a[j + 1];
        }
        index.block_p->size--;
    }
    // update total size                                    //-
    size--;
}                                               //-
                                                //-
void Dynamic_array::remove(int start, int end) {                        //-
}                                               //-
                                                //-
// ********** private functions **********                          //-
                                                //-
// purpose                                          //-
//  return b where                                      //-
//      if i < size                                 //-
//          b.block_p->a[b.i] is the ith element overall                //-
//      else                                        //-
//          b.block_p->a[b.i-1] is the i-1st element overall            //-
//                                              //-
//      if b.block_p == head_p                              //-
//          b.pre_block_p is NULL                           //-
//      else                                        //-
//          b.pre_block_p points to block preceding b.block_p           //-
// preconditions                                        //-
//  i in [1..size]                                      //-
Dynamic_array::Block_position Dynamic_array::find_block(int i) {                //-
    Block_position position;                                //-
                                                //-
    // scan Block list                                  //-
    position.i = i;                                     //-
    position.pre_block_p = NULL;                                //-
    for (position.block_p = head_p;                             //-
    position.block_p != NULL;                               //-
    position.block_p = position.block_p->next_p) {                      //-
        // found in current block                           //-
        if (position.i < position.block_p->size) {                  //-
            break;                                  //-
        }                                       //-
                                                //-
        // special case: insert just after last element                 //-
        if (i == size && position.block_p->next_p == NULL) {                //-
            break;                                  //-
        }                                       //-
                                                //-
        // not found yet: advance                           //-
        position.pre_block_p = position.block_p;                    //-
        position.i -= position.block_p->size;                       //-
    }                                           //-
                                                //-
    return position;                                    //-
}                                               //-
                                                //-
// purpose                                          //-
//  create a new linked list which is a copy of the list pointed to p           //-
//  return a pointer to the head of the new linked list                 //-
// preconditions                                        //-
//  p is the head of a possibly empty linked list of blocks                 //-
Dynamic_array::Block * Dynamic_array::copy_blocks(Block * p) {                  //-
    Block * new_head_p = NULL;                              //-
    Block * new_p;                                      //-
    while (p != NULL) {                                 //-
        // allocate and link in new block                       //-
        if (new_head_p == NULL) {                           //-
            new_p = new Block;                          //-
            new_head_p = new_p;                         //-
        } else {                                    //-
            new_p->next_p = new Block;                      //-
            new_p = new_p->next_p;                          //-
        }                                       //-
                                                //-
        // copy the elements                                //-
        new_p->size = p->size;                              //-
        for (int i = 0; i < p->size; i++) {                     //-
            new_p->a[i] = p->a[i];                          //-
        }                                       //-
                                                //-
        // advance                                  //-
        p = p->next_p;                                  //-
    }                                           //-
                                                //-
    // terminate new list                                   //-
    if (new_head_p != NULL) {                               //-
        new_p->next_p = NULL;                               //-
    }                                           //-
                                                //-
    return new_head_p;                                  //-
}                                               //-
                                                //-
// purpose                                          //-
//  insert the list headed by src_p into the list headed by head_p              //-
//  if dst_p is NULL                                    //-
//      insert the list at the start of the list headed by head_p           //-
//  else                                            //-
//      insert the list just after block dst_p                      //-
// preconditions                                        //-
//  list headed by src_p is non-empty                           //-
//  list headed by src_p has no blocks in common with the list headed by head_p     //-
void Dynamic_array::insert_blocks(Block * dst_p, Block * src_p) {               //-
    // find the last block in the list headed by src_p                  //-
    Block * p = src_p;                                  //-
    while (p->next_p != NULL) {                             //-
        p = p->next_p;                                  //-
    }                                           //-
                                                //-
    // insert at head                                   //-
    if (dst_p == NULL) { // insert at head                          //-
        p->next_p = head_p;                             //-
        head_p = src_p;                                 //-
                                                //-
    // insert after dst_p                                   //-
    } else { // insert after dst_p                              //-
        p->next_p = dst_p->next_p;                          //-
        dst_p->next_p = src_p;                              //-
    }                                           //-
}                                               //-
                                                //-
// purpose                                          //-
//  remove the blocks pointed to by start_p and end_p, and all the blocks between       //-
// preconditions                                        //-
//  start_p and end_p point to blocks in the list headed by head_p              //-
//  end_p points to either the same block as start_p or a block to its right        //-
//  if start_p == head_p                                    //-
//      pre_start_p == NULL                             //-
//  else                                            //-
//      pre_start_p points to the block immediately preceding start_p           //-
//                                              //-
void Dynamic_array::remove_blocks(Block * pre_start_p, Block * start_p, Block * end_p) {    //-
    // release the blocks                                   //-
    while (1) {                                     //-
        // release start_p                              //-
        Block * p = start_p->next_p;                            //-
        delete start_p;                                 //-
                                                //-
        // advance                                  //-
        if (start_p == end_p) {                             //-
            break;                                  //-
        } else {                                    //-
            start_p = p;                                //-
        }                                       //-
    }                                           //-
                                                //-
    // link left and right sublists                             //-
    if (pre_start_p == NULL) {                              //-
        head_p = end_p->next_p;                             //-
    } else {                                        //-
        pre_start_p->next_p = start_p->next_p;                      //-
    }                                           //-
}                                               //-

int a[BLOCK_SIZE];

只有 5 个元素从 0..4 开始索引。

因此 d.insert(11,5); 和 d.remove(5);

将引发异常。