读取类的析构函数中的位置时发生访问冲突
Access violation reading location in a destructor of a class
我已经构建了Graph类、一个构造函数和一个析构函数。我的问题是:当我编译这个代码时,我在delete [] mat[i];
行得到一个错误,错误是"读取位置0xDDDDDCD的访问冲突"我不知道我做错了什么。我的意思是,我只删除我动态分配的内存。后期编辑:即使我用这个代替我的方法:
Graph(int nr_noduri) {
this->nr_noduri = nr_noduri;
mat = new bool* [nr_noduri];
for (int i = 0; i < nr_noduri; i++) {
mat[i] = new bool[nr_noduri];
}
for (int i = 0; i < nr_noduri; i++) {
for (int j = 0; j < nr_noduri; j++) {
mat[i][j] = 0;
}
}
}
我的代码是:
#include <iostream>
#include <cstdlib>
using namespace std;
class Graph {
bool** mat;
int nr_noduri;
public:
Graph(int nr_noduri) {
this->nr_noduri = nr_noduri;
mat = (bool**)calloc(nr_noduri, sizeof(bool*));
for (int i = 0; i < nr_noduri; i++) {
mat[i] = (bool*)calloc(nr_noduri, sizeof(bool));
}
}
int size() {
return nr_noduri;
}
void addArc(int v, int w) {
if (v < nr_noduri && w < nr_noduri) {
mat[v][w] = true;
}
else cout << "Not enough nodes !" << endl;
}
bool isArc(int v, int w) {
return (mat[v][w] == true);
}
void print() {
for (int i = 0; i < nr_noduri; i++) {
cout << endl;
for (int j = 0; j < nr_noduri; j++) {
cout << mat[i][j] << " ";
}
}
cout << endl;
}
~Graph() {
//cout << nr_noduri;
for (int i = 0; i < nr_noduri; i++) {
delete [] mat[i];
}
delete[] mat;
}
friend void dfs(Graph g, int v, bool vazut[]);
};
void dfs(Graph g, int v, bool vazut[]) {
int w;
vazut[v] = true;
for (w = 0; w < g.size(); w++) {
if (g.isArc(v, w) && !vazut[w]) {
cout << v << "->" << w;
dfs(g, w, vazut);
}
}
}
int main() {
int nr_noduri;
cin >> nr_noduri;
Graph v(nr_noduri);
v.print();
v.addArc(1, 2);
v.addArc(2, 5);
cout << v.isArc(1, 2) << endl;
v.print();
bool vazut[100];
dfs(v, 1, vazut);
return 0;
}
您不能使用delete
来解除分配由calloc
(或任何malloc
函数族(分配的内存。请改用new
来分配内存。
Graph(int nr_noduri) {
this->nr_noduri = nr_noduri;
mat = new bool*[nr_noduri];
for (int i = 0; i < nr_noduri; i++) {
mat[i] = new bool[nr_noduri];
}
}
更好的是,使用std::vector<std::vector<bool>>
来保存数据。
class Graph {
std::vector<std::vector<bool>> mat;
Graph(int nr_noduri) : mat(nr_noduri, std::vector<bool>(nr_noduri) {}
...
};
此行:
void dfs(Graph g, int v, bool vazut[])
具有按值传递的第一个参数g
,因此将是传入的Graph
的临时副本。如果Graph
没有正确的复制语义,则对dfs
的调用将导致未定义的行为。
CCD_ 12包含指向动态分配的存储器的成员CCD_。此外,Graph
有一个析构函数,它在这个内存上发出delete []
。因此,当Graph
被复制时,mat
指针也被复制。现在有两个mat
指针指向同一内存。当临时超出范围时,将在mat
指针上发出delete []
。
这可能就是您遇到运行时问题的原因——mat
所指向的内存已经被删除,您将再次删除它。
要解决此问题,您有两个选择:
- 通过引用
dfs
而不是通过值传递Graph
,或者 - 修复
Graph
类以正确处理副本
对于项目1:
void dfs(Graph& g, int v, bool vazut[])
从而避免了临时副本的制作。
然而,对我来说,这只是一个创可贴解决方案,可以避免遇到复制错误(尽管无论如何都应该通过引用传递(。
更好的方法是使Graph
类可以安全地复制,这意味着可以正确地进行复制,而不会出现您现在看到的"双重删除"错误。
要做到这一点,请添加以下功能来完成规则3,以允许正确执行复制:
#include <algorithm>
//…
Graph(const Graph& rhs) : mat(nullptr), nr_noduri(rhs.nr_noduri)
{
mat = new bool* [rhs.nr_noduri];
for (int i = 0; i < rhs.nr_noduri; i++) {
mat[i] = new bool[rhs.nr_noduri];
}
for (int i = 0; i < rhs.nr_noduri; i++) {
for (int j = 0; j < rhs.nr_noduri; j++) {
mat[i][j] = rhs.mat[i][j];
}
}
}
Graph& operator=(const Graph& rhs)
{
if ( this != &rhs )
{
Graph temp(rhs);
std::swap(temp.mat, mat);
std::swap(temp.nr_noduri, nr_noduri);
}
return *this;
}
您的类缺少用户定义的复制构造函数和赋值运算符(使用复制/交换习惯用法(。
另一个无关的问题是构建2D矩阵的方式。您使用的是最糟糕的方法之一,即分配指针,然后在循环中分配每一行。
它不仅是速度方面的瓶颈(为每一行调用分配器(,而且由于行被分配在堆的不同部分,以及堆碎片,它对缓存不友好。如果循环中对new[]
的其中一个调用失败,如果不想泄漏内存,就必须回滚对new[]
的所有成功调用。
有关创建二维阵列的更好方法,请参见此解决方案。
- 读取类的析构函数中的位置时发生访问冲突
- 是否可以访问类数据成员并在析构函数中对它们执行操作?
- 从析构函数访问模板类构造函数的参数,可以吗?
- 为什么我可以访问已删除但在C++中具有虚拟析构函数的对象?
- 在析构函数 c++ 中访问所有者
- Qlist<QCameraInfo> 导致 QList 析构函数中的访问冲突
- 为什么我在使用组合而不是继承时得到 C4624(无法访问基类析构函数)
- 在析构函数调用后访问成员变量
- mfc应用程序结束后,CMainFrame的析构函数调用发生访问冲突
- 从本地类的 C++ 析构函数访问返回代码
- 为虚拟析构函数指定的冲突类型属性
- 在析构函数调用时访问冲突读取位置0xfeeefe2
- 仅在调试时std::string析构函数中存在访问冲突
- 复制构造函数之后的flann::Index的析构函数产生访问冲突
- 限制对C++构造函数和析构函数的访问
- 为什么只有在声明了自定义构造函数时,基类析构函数才能访问
- 无法访问类析构函数中的联合成员
- Parasoft冲突:析构函数~dest应该是虚的
- 虚拟析构函数导致访问冲突
- C++析构函数EXC_BAD_ACCESS无法访问内存