当更改类的私有部分时,访问冲突写入位置,c++

Access violation writing location when changing private part of a class, c++

本文关键字:访问冲突 c++ 位置 分时      更新时间:2023-10-16

我正在写一个Deque(不接受STL,主要思想是自己写Deque)。得到一个:

Unhandled exception at 0x009932C1 in Deque.exe: 0xC0000005:
Access violation writing location 0xFFFFFFFC.

问题在行:

buffer[tail++] = element;

我想改变一个元素,它在类中是私有的。会是什么问题呢?

在Visual Studio 2012中工作,语言- c++。代码:

#include "stdafx.h"
#include <iostream>
#include <cassert>
#include <deque>
using namespace std;
class Deque
{
public:
    void PushBack( int element );
    bool IsEmpty() const { return head == tail; }
    void clearDeque();
    void setBufSize( size_t size )
    {
        bufferSize = size;
        int* buffer = new int[bufferSize];
        for (size_t i = 0; i < bufferSize; i++)
            buffer[i] = 0;
    }
    int getDeque()
    {
        while ( head != tail )
        {
            if ( head == bufferSize )
            {
                head = 0;
            }
            return buffer[head++];
        }
    }
private:
    int* buffer;
    int bufferSize;
    int head;
    int tail;
};
void Deque :: PushBack( int element )
{
    buffer[tail++] = element;
    if ( ( tail == bufferSize ) && ( tail != head ) )
        tail = 0;
}
int main()
{
  Deque myDeque;
  deque <int> TrueDeque;
  myDeque.setBufSize(15);
  myDeque.PushBack(44);
  return 0;
}

(除了其他人注意到的关于初始化成员变量失败的问题)

您使用了多个具有相同名称的变量,可能是无意的。

在成员函数

void setBufSize( size_t size )
{
    bufferSize = size;
    int* buffer = new int[bufferSize];
    for (size_t i = 0; i < bufferSize; i++)
        buffer[i] = 0;
}

buffer是一个局部变量。您没有使用或更新同名的成员变量。

尝试一个简单的赋值buffer = new int[bufferSize];代替变量声明。或者更好,使用std::vector代替。

应该在构造函数中初始化每个成员。在你的代码中,你使用tail没有初始化它,所以它有一些随机值。

您在哪里初始化尾部?(或负责人)

我建议您在您的构造函数中这样做,以便您可以利用RAII范例,如果您还需要其他资源。

您的类没有初始化其数据成员。由于它们都是原始类型(intint*),读取它们的值会产生未定义的行为,即任何事情都可能发生,包括随机崩溃。具体来说,在您的例子中,headtail被读取,但从未被赋值或初始化。

你的类需要一个带有初始化列表的构造函数。例如:

Deque::Deque() :
    buffer(0),
    bufferSize(0),
    head(0),
    tail(0)
{
}

实际上,去掉setBufSize并将其功能直接移到构造函数中(以及在适用的初始化列表中)。

头和尾都没有初始化。

setBufSize函数也不检查缓冲区是否已经分配。在这种情况下,当您多次调用该函数时,就会发生内存泄漏。

  void setBufSize( size_t size )
  {
    bufferSize = size;
int* buffer = new int[bufferSize];
for (size_t i = 0; i < bufferSize; i++)
  buffer[i] = 0;
  }

我想语句

有一个错字。
int* buffer = new int[bufferSize];

应该有

buffer = new int[bufferSize];

如果你的类没有显式构造函数,或者在类定义中添加初始化器,你至少可以在这个成员函数中初始化head和tail。例如

//...
private:
    int* buffer = nullptr;
    int bufferSize = 0;
    int head = 0;
    int tail = 0;

类需要定义析构函数、复制赋值操作符和复制构造函数,或者将后两者定义为删除