删除指向指针的指针会导致 "Invalid address specified to RtlValidateHeap" 错误
Deleting a pointer to a pointer causes "Invalid address specified to RtlValidateHeap" error
我正在解决一个简单的数学问题,需要不断地向答案集中添加解决方案。所以我设计了一个class,里面有一个指向指针的指针。每当制定出新的解决方案时,我都会定义另一个新的临时指针,指向一个指针来保存答案集的数据,并扩大答案集的容量并重新初始化它。然后复制以前的数据并将新的解决方案存储到答案集中。
在删除临时指针时,程序总是崩溃,出现“Invalid address specified to RtlValidateHeap”错误。
就是删除它指向的指针数组。
删除相应的代码使一切正常。但是我猜想会因为缺少 delete[]
.
而导致更大数据集的内存泄漏
我认为我以正确的方式使用了复制功能,并使每个未使用的指针都指向 NULL。
所以,这是我的代码:
#include <iostream>
#include "CChickProblem.h"
using namespace std;
int main(int argc, char const *argv[])
{
int n;
cin >> n;
while (n--)
{
int a, b;
cin >> a >> b;
CChickProblem c(a, b);
c.findSolution();
c.printSolution();
}
return 0;
}
CChickProblem.h:
#pragma once
class CChickProblem
{
private:
int cockNum, henNum, chickNum, answerNum, totalNum, totalPrice;
static int singleCockPrice, singleHenPrice, tripleChickPrice, chickenKindNum;
int **answer;
public:
CChickProblem(int money, int number);
~CChickProblem();
void findSolution();
void printSolution();
};
CChickProblem.cpp:
#include <iostream>
#include "CChickProblem.h"
using namespace std;
int CChickProblem::singleCockPrice = 5;
int CChickProblem::singleHenPrice = 3;
int CChickProblem::tripleChickPrice = 1;
int CChickProblem::chickenKindNum = 3;
CChickProblem::CChickProblem(int number, int money)
{
totalNum = number;
totalPrice = money;
cockNum = henNum = chickNum = answerNum = 0;
answer = nullptr;
}
CChickProblem::~CChickProblem()
{
for (int i = 0; i < answerNum; i++)
{
delete[] * (answer + i);
}
delete[] answer;
}
void CChickProblem::findSolution()
{
for (cockNum = 0; cockNum <= (totalPrice / singleCockPrice); cockNum++)
{
for (henNum = 0; henNum <= (totalPrice / singleHenPrice); henNum++)
{
for (chickNum = 0; chickNum <= (totalPrice / tripleChickPrice * 3); chickNum += 3)
{
if (cockNum * henNum * chickNum != 0 && cockNum + henNum + chickNum == totalNum && cockNum * singleCockPrice + henNum * singleHenPrice + chickNum / 3 * tripleChickPrice == totalPrice)
{
int **extra = new int *[answerNum];
for (int i = 0; i < answerNum; i++)
{
*(extra + i) = new int[chickenKindNum];
}
copy(answer, answer + answerNum, extra);
answer = new int *[++answerNum];
for (int i = 0; i < answerNum; i++)
{
*(answer + i) = new int[chickenKindNum];
}
copy(extra, extra + answerNum - 1, answer);
if (extra)
{
for (int i = 0; i < answerNum - 1; i++)
{
if (extra[i])
{
delete[] extra[i];//Where crashes!!
extra[i] = nullptr;
}
}
delete[] extra;
extra = nullptr;
}
*(answer + answerNum - 1) = new int[chickenKindNum];
for (int i = 0; i < chickenKindNum; i++)
{
switch (i)
{
case 0:
*(*(answer + answerNum - 1) + i) = cockNum;
break;
case 1:
*(*(answer + answerNum - 1) + i) = henNum;
break;
case 2:
*(*(answer + answerNum - 1) + i) = chickNum;
break;
default:
break;
}
}
}
}
}
}
}
void CChickProblem::printSolution()
{
cout << answerNum << endl;
for (int i = 0; i < answerNum; i++)
{
for (int j = 0; j < chickenKindNum; j++)
{
cout << *(*(answer + i) + j);
if (j != 2)
{
cout << ' ';
}
else
{
cout << endl;
}
}
}
}
请帮帮我,谢谢!
好的,伙计们。经过几天的测试和尝试,我弄清楚了这个愚蠢的问题在哪里。尝试删除指针的 delete [] extra[i]
是完全不必要的,因为它会删除堆上的指向数据,这些数据被安排在下面的代码中重用,而不删除指针本身。而且,由于它已经删除了堆中的数据,当程序在析构函数结束时,它将找不到要析构的东西,从而引发错误。
因此,在不删除指向数据的情况下销毁指针的正确方法是创建另一个指向原始指向数据的指针,以防找不到它们并使原始指针指向 NULL。
在我的程序中,应该是复制进度后删除指向指针的指针。
我正在解决一个简单的数学问题,需要不断地向答案集中添加解决方案。所以我设计了一个class,里面有一个指向指针的指针。每当制定出新的解决方案时,我都会定义另一个新的临时指针,指向一个指针来保存答案集的数据,并扩大答案集的容量并重新初始化它。然后复制以前的数据并将新的解决方案存储到答案集中。
在删除临时指针时,程序总是崩溃,出现“Invalid address specified to RtlValidateHeap”错误。 就是删除它指向的指针数组。
删除相应的代码使一切正常。但是我猜想会因为缺少 delete[]
.
我认为我以正确的方式使用了复制功能,并使每个未使用的指针都指向 NULL。
所以,这是我的代码:
#include <iostream>
#include "CChickProblem.h"
using namespace std;
int main(int argc, char const *argv[])
{
int n;
cin >> n;
while (n--)
{
int a, b;
cin >> a >> b;
CChickProblem c(a, b);
c.findSolution();
c.printSolution();
}
return 0;
}
CChickProblem.h:
#pragma once
class CChickProblem
{
private:
int cockNum, henNum, chickNum, answerNum, totalNum, totalPrice;
static int singleCockPrice, singleHenPrice, tripleChickPrice, chickenKindNum;
int **answer;
public:
CChickProblem(int money, int number);
~CChickProblem();
void findSolution();
void printSolution();
};
CChickProblem.cpp:
#include <iostream>
#include "CChickProblem.h"
using namespace std;
int CChickProblem::singleCockPrice = 5;
int CChickProblem::singleHenPrice = 3;
int CChickProblem::tripleChickPrice = 1;
int CChickProblem::chickenKindNum = 3;
CChickProblem::CChickProblem(int number, int money)
{
totalNum = number;
totalPrice = money;
cockNum = henNum = chickNum = answerNum = 0;
answer = nullptr;
}
CChickProblem::~CChickProblem()
{
for (int i = 0; i < answerNum; i++)
{
delete[] * (answer + i);
}
delete[] answer;
}
void CChickProblem::findSolution()
{
for (cockNum = 0; cockNum <= (totalPrice / singleCockPrice); cockNum++)
{
for (henNum = 0; henNum <= (totalPrice / singleHenPrice); henNum++)
{
for (chickNum = 0; chickNum <= (totalPrice / tripleChickPrice * 3); chickNum += 3)
{
if (cockNum * henNum * chickNum != 0 && cockNum + henNum + chickNum == totalNum && cockNum * singleCockPrice + henNum * singleHenPrice + chickNum / 3 * tripleChickPrice == totalPrice)
{
int **extra = new int *[answerNum];
for (int i = 0; i < answerNum; i++)
{
*(extra + i) = new int[chickenKindNum];
}
copy(answer, answer + answerNum, extra);
answer = new int *[++answerNum];
for (int i = 0; i < answerNum; i++)
{
*(answer + i) = new int[chickenKindNum];
}
copy(extra, extra + answerNum - 1, answer);
if (extra)
{
for (int i = 0; i < answerNum - 1; i++)
{
if (extra[i])
{
delete[] extra[i];//Where crashes!!
extra[i] = nullptr;
}
}
delete[] extra;
extra = nullptr;
}
*(answer + answerNum - 1) = new int[chickenKindNum];
for (int i = 0; i < chickenKindNum; i++)
{
switch (i)
{
case 0:
*(*(answer + answerNum - 1) + i) = cockNum;
break;
case 1:
*(*(answer + answerNum - 1) + i) = henNum;
break;
case 2:
*(*(answer + answerNum - 1) + i) = chickNum;
break;
default:
break;
}
}
}
}
}
}
}
void CChickProblem::printSolution()
{
cout << answerNum << endl;
for (int i = 0; i < answerNum; i++)
{
for (int j = 0; j < chickenKindNum; j++)
{
cout << *(*(answer + i) + j);
if (j != 2)
{
cout << ' ';
}
else
{
cout << endl;
}
}
}
}
请帮帮我,谢谢!
好的,伙计们。经过几天的测试和尝试,我弄清楚了这个愚蠢的问题在哪里。尝试删除指针的 delete [] extra[i]
是完全不必要的,因为它会删除堆上的指向数据,这些数据被安排在下面的代码中重用,而不删除指针本身。而且,由于它已经删除了堆中的数据,当程序在析构函数结束时,它将找不到要析构的东西,从而引发错误。
因此,在不删除指向数据的情况下销毁指针的正确方法是创建另一个指向原始指向数据的指针,以防找不到它们并使原始指针指向 NULL。
在我的程序中,应该是复制进度后删除指向指针的指针。