【问题标题】:new int[] throws 'Access Violation' exceptionnew int[] 抛出“访问冲突”异常
【发布时间】:2011-04-17 06:00:21
【问题描述】:

我一直在研究自定义 Vector 类。在 Microsoft 编译器上一切正常,但是当我在 Borland 上尝试时,我遇到了一个非常奇怪的错误。

Borland 在插入函数内部抛出异常; 正是在调用复制构造函数“Vector temp(*this);”时在

"array_ = new int[rhs.size_];"线

void Vector::insert(int value, unsigned position) throw(SubscriptError)
{
    check_bounds(position);
    Vector temp(*this);
    int tmpSize= size_;
    temp.size_++;
    size_++;
    for (unsigned int i=tmpSize; i > position; i--)
    {
        temp[i] = temp[i-1];
    }
    temp[position] = value;

   //array_= temp.array_;
    for(unsigned int i = 0; i < size_; i++)
    {
        array_[i]= temp.array_[i];
    }
}

这是我的复制构造函数;

Vector::Vector(const Vector& rhs)
{
    array_ = new int[rhs.size_];
    size_ = rhs.size_;
    for(unsigned int i = 0; i < rhs.size_; i++)
    {
        array_[i] = rhs.array_[i];
    }
}

最后这是 main();

 std::cout << "push_back 5 integers:\n";
 for (int i = 0; i < 5; i++)
 {
  a.push_back(i);
   Print(a);
 }

std::cout << "insert(99, 3):\n";
a.insert(99, 3);
Print(a);
std::cout << "insert(98, 0):\n";
a.insert(98, 0);
Print(a);
std::cout << "insert(97, 6):\n";
a.insert(97, 6);
Print(a);

奇怪的是第一次插入调用(a.insert(99, 3)) 工作正常,第二次调用时崩溃(a.insert(98, 0))

这是完整的头文件

namespace CS170
 {
    class SubscriptError
    {
     public:
       SubscriptError(int Subscript) : subscript_(Subscript) {};
       int GetSubscript(void) const { return subscript_; }

     private:
    int subscript_;
    };

class Vector
{
public:

    static const int NO_INDEX = -1;

    struct SortResult
    {
        unsigned compares;
        unsigned swaps;
    };

    // Default constructor
    Vector(void);

    // Destructor
    ~Vector();

    // Copy constructor
    Vector(const Vector& rhs);

    // Constructor to create a Vector from an array
    Vector(const int array[], unsigned size);

    // Adds a node to the front of the list
    void push_back(int value);

    // Adds a node to the end of the list
    void push_front(int value);

    // Removes the last element. Does nothing if empty.
    void pop_back(void);

    // Removes the first element. Does nothing if empty.
    void pop_front(void);

    // Inserts a new node at the specified position. Causes an
    // abort() if the position is invalid. (Calls check_bounds)
    void insert(int value, unsigned position) throw(SubscriptError);

    // Removes an element with the specified value (first occurrence)
    void remove(int value);

    // Deletes the underlying array and sets size_ to 0
    void clear(void);

    // Return true if the vector is empty, otherwise, false
    bool empty(void) const;

    // Assignment operator
    Vector& operator=(const Vector& rhs);

    // Concatenates a vector onto the end of this vector.
    Vector& operator+=(const Vector& rhs);

    // Concatenates two Vectors.
    Vector operator+(const Vector& rhs) const;

    // Subscript operators.
    int operator[](unsigned index) const throw(SubscriptError);
    int& operator[](unsigned index) throw(SubscriptError);

    // Returns the number of elements in the vector.
    unsigned size(void) const;

    // Returns the size of the underlying array
    unsigned capacity(void) const;

    // The number of memory allocations that have occurred
    unsigned allocations(void) const;

    // This searches the vector using a binary search instead
    // of a linear search. The data must be sorted. Returns
    // the index. If not found, returns CS170::Vector::NO_INDEX.
    // DO NOT SORT THE DATA IN THIS FUNCTION!!    
    int bsearch(int value) const;

    // Sorts the elements using a selection sort. 
    // Returns the number of swaps/comparisons that occurred.
    SortResult selection_sort(void);

    // Sorts the elements using a bubble_sort.
    // Returns the number of swaps/comparisons that occurred.
    SortResult bubble_sort(void);

    void swap(int &a, int& b);

    void swapv(Vector &other);

    void reverse(void);

    bool operator==(const Vector& rhs) const;

    void shrink_to_fit(void);

private:
    int *array_;        // The dynamically allocated array
    unsigned size_;     // The number of elements in the array
    unsigned capacity_; // The allocated size of the array
    unsigned allocs_;   // Number of allocations (resizes)

    // Private methods...
    void check_bounds(unsigned index) const throw(SubscriptError);
    void grow(void);

    // Other private methods...
};

   }// namespace CS170

        #endif // VECTOR_H

【问题讨论】:

  • @Brian:为什么rhs.size_ 是私有的会有问题?一个类可以完全访问其内部,因此您当然可以访问您自己的另一个 Vector 对象的 size_
  • 不要使用异常规范(函数头中的 throw(SubscriptError)),它们将从 C++ 中删除。

标签: c++ dynamic vector c++builder access-violation


【解决方案1】:

您没有(明显地)在insert() 中调整array_ 的大小。这意味着您将始终在其分配的内存末尾写入一个元素。

复制整个数组(两次)会导致非常昂贵的插入。你想达到什么在std::vector 中无法实现的目标?

【讨论】:

    【解决方案2】:

    在我看来,当您第一次拨打insert() 时,就会造成损害。当您插入一个元素时,您还必须增加分配给您的成员array_ 的字节数。您只是增加了size_,但是增加实际array_ 的大小呢?

    例如,您的insert() 中正在发生类似以下情况:

    int size = 5;
    int *p = new int[size];
    // ... populate p[i] (i = 0 to i = size - 1)
    size ++;
    p[size - 1] = VALUE; // oops ... incremented 'size' but before that reallocate to 'p'
    

    调用后,首先插入你的堆栈将已经损坏。所以第二次它崩溃了。只需根据相应的代码更改进行验证。

    附注,

    • 感觉可以写insert(),更优化。我觉得不需要临时复制完整的Vector&lt;&gt;
    • 另外,尝试为array_ 分配比实际需要更多的字节数。这样您就不必多次重新分配
    • 尝试从 STL 中查看实际 vector 的源代码以提高效率。

    【讨论】:

      【解决方案3】:

      在您的插入函数中,您不会为新插入的项目分配内存,并且在第一次插入后,复制 ctr 会尝试读取抛出异常的行上未分配的内存。解决方案是最初分配更多内存(这就是为什么容量用于典型向量实现的原因)或在每次插入时增加分配的数组。您必须在这两个解决方案上实现重新分配,但在第一个解决方案中,它的调用频率会降低。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-12
        • 1970-01-01
        • 2022-01-08
        • 1970-01-01
        • 2018-05-19
        • 1970-01-01
        • 2021-07-02
        • 2021-06-04
        相关资源
        最近更新 更多