gpt4 book ai didi

c++ - 内存泄漏在哪里?二维数组类

转载 作者:行者123 更新时间:2023-11-30 05:36:49 25 4
gpt4 key购买 nike

我把这个程序提交给一个类(class),错误消息说有一些内存泄漏,但我找不到它们(我什至问过另一个教授)

这是错误信息:

==27796== HEAP SUMMARY:
==27796== in use at exit: 160 bytes in 2 blocks
==27796== total heap usage: 192 allocs, 190 frees, 21,989 bytes allocated
==27796==
==27796== 160 bytes in 2 blocks are definitely lost in loss record 1 of 1
==27796== at 0x402ADFC: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==27796== by 0x804D5C2: SweeperGrid::SweeperGrid(SweeperGrid const&) (in /tmp/grading20151030-8173-zfd6af-0/sweepertest)
==27796== by 0x804BF57: main (sweepertest.cpp:357)

下面是我使用 new 或 delete 的任何代码:

//显式值构造函数

 SweeperGrid::SweeperGrid(const int initialRows, const int initialCols, const int density){
if ((initialRows<5 || initialCols<5) || (density<25 || density>75)) {
throw out_of_range("Grid not large enough (number of rows or columns cannot be fewer than 5) or density is too low or high (must be between 25% and 75%)");
}

numRows = initialRows;
numColumns = initialCols;
numBombs = 0;

grid = new SweeperCell*[numRows];
for(int i=0; i <numRows; i++){
grid[i] = new SweeperCell[numColumns];
}

srand(time(0));
for(int i=0; i<numRows; i++){
for (int j=0; j<numColumns; j++){
if(rand()%100+1<density){
PlaceBomb(i, j);
}
}
}
}

//复制构造函数

SweeperGrid::SweeperGrid(SweeperGrid const & source){
numRows=source.GetRows();
numColumns=source.GetColumns();
numBombs=source.GetBombs();

grid = new SweeperCell * [numRows];
for(int i=0; i < numRows; i++){
grid[i] = new SweeperCell[numColumns];
}

for(int i=0; i<numRows; i++){
for (int j=0; j<numColumns; j++){
grid[i][j] = source.At(i, j);
}
}
}

//析构函数

SweeperGrid::~SweeperGrid(){
for(int i=0; i<numRows; i++){
delete [] grid[i];
}
delete [] grid;
}

//功能:重载赋值运算符

void SweeperGrid::operator= (SweeperGrid const & source){
numRows=source.GetRows();
numColumns=source.GetColumns();
numBombs=source.GetBombs();

for(int i=0; i<numRows; i++){
delete [] grid[i];
}
delete [] grid;

grid = new SweeperCell * [numRows];
for(int i=0; i < numRows; i++){
grid[i] = new SweeperCell[numColumns];
}

for(int i=0; i<numRows; i++){
for (int j=0; j<numColumns; j++){
grid[i][j] = source.At(i, j);
}
}
}

最佳答案

您的问题是由删除的行数与分配的行数不同引起的:

void SweeperGrid::operator= (SweeperGrid const & source){
numRows=source.GetRows(); // numRows becomes the assigned number of rows here.
// This is a problem, because now you don't remember how many
// rows you need to delete!
numColumns=source.GetColumns();
numBombs=source.GetBombs();

for(int i=0; i<numRows; i++){ // you delete rows here, but the number of rows found in
// the NEW grid, not the old one.
delete [] grid[i];
}
delete [] grid;

...
}

一个简单的修复:

void SweeperGrid::operator= (SweeperGrid const & source){

for(int i=0; i<numRows; i++){ // you delete rows here, while you still remember
// how many you should delete
delete [] grid[i];
}
delete [] grid;
numRows=source.GetRows(); // numRows becomes the assigned number of rows here.
// This is not a problem, because now you don't need to
// remember how many rows you need to delete.
numColumns=source.GetColumns();
numBombs=source.GetBombs();
...
}

这类问题正是为什么手动使用 deletenew 是一个糟糕的想法——此外,它不是异常安全的(什么如果在构造函数中,在你已经分配了其他东西之后分配其中一行失败会发生什么?你会丢失你之前在构造函数中分配的每一 block 内存,直到你关闭程序才可以看到。)

更简单的解决方案是应用 Resource Acquisition Is Initialization惯用语(简称 RAII)并使用一个容器来控制资源,方法是在构建时分配资源并在销毁时释放资源—— vector 将为您完成此操作,smart 等漂亮的东西也会这样做。 pointers .这消除了您处理每一个的责任。单例的。分配。如果。甚至。 A。单例的。一。失败,因为使用 RAII,如果失败,资源已经分配干净它们自己了。

举个例子,如果我为 grid 使用一个 vector 的 vector ,而不是一个 c 风格的动态数组到一堆 c 风格的动态数组,赋值运算符可能看起来像这样:

void SweeperGrid::operator= (SweeperGrid const & source){
numRows=source.GetRows();
numColumns=source.GetColumns();
numBombs=source.GetBombs();

grid = source.grid;
}

关于c++ - 内存泄漏在哪里?二维数组类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33444830/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com