我正在为函数近似编写简单的ANN(神经网络)。我收到了消息:“堆已损坏”。我发现很少有建议如何解决它,但没有任何帮助。 我在这个函数的第一行遇到错误:
void LU(double** A, double** &L, double** &U, int s){
U = new double*[s];
L = new double*[s];
for (int i = 0; i < s; i++){
U[i] = new double[s];
L[i] = new double[s];
for (int j = 0; j < s; j++)
U[i][j] = A[i][j];
}
for (int i = 0, j = 0; i < s; i = ++j){
L[i][j] = 1;
for (int k = i + 1; k < s - 1; k++){
L[k][j] = U[k][j] / U[i][j];
double* vec_t = mul(U[i], L[k][j], s);
for (int z = 0; z < s; z++)
U[k][z] = U[k][z] - vec_t[z];
delete[] vec_t;
}
}
};
正如我从debagger的信息中所理解的那样:已经传递了两个数组(U和L)以在内存中使用一些地址。这很奇怪,因为我没有初始化它。我调用这个函数两次,第一次它很好地工作(好吧,至少它工作),但在第二次调用它崩溃。我不知道如何解决它
有整个项目的链接:CLICK
我在Windows 7 x64下的MS Visual Studio 2013中工作。
更新
根据下面的一些评论,我应该提供一些附加信息
首先,抱歉代码质量。我只为自己写了2天
第二,当我说“第二次通话”时,我的意思是,当我需要获得S的决定因素时,我首先调用LU(我使用LU分解这个)并且它在没有任何崩溃的情况下工作。当我试图得到矩阵的逆(相同的,S)时,再次调用它。当我在矩阵的[0,0]点调用detLU时(为了得到辅助因子)我得到了这个崩溃。
第三,如果我正确地从debagger获取信息,则数组L和U在已经定义的内存地址的第二次调用时传递函数。我无法理解为什么,因为在LU调用之前我刚写过“double ** L; double ** U;”没有任何初始化。
我可以尝试提供一些额外的调试信息或一些测试,如果有人解释我到底要做什么。
答案 0 :(得分:1)
您遇到堆损坏错误/崩溃的点通常只是实际堆溢出/下溢或过去某个其他时间点的其他内存错误的症状。这就是为什么堆损坏很难追查的原因。
你有很多代码,所有的双指针很难跟踪,但我确实注意到一个潜在的问题:
double** initInWeights(double f, int h, int w) {
double** W = new double*[h];
for (int i = 0; i < 10; i++) {
W[i] = new double[w];
如果W[]
小于10,循环将溢出h
。可能是代码中某处有缓冲区溢出/下溢或者在释放后使用内存。代码的复杂性和设计使得难以一目了然。
你是否有理由使用原始双指针而不仅仅是std::vector<std::vector<double>>
?这将删除所有手动内存管理代码,使您的代码更短,更简单,更重要的是消除堆损坏问题。
除非你应该仔细检查所有手动分配的内存是否正确,访问循环永远不会超出范围。
更新 - 我认为您的问题可能在于extract()
中matrix.cpp
函数中的缓冲区溢出:
double** extract(double** mat, int s, int col, int row)
{
double** ext = new double*[s - 1];
for (int i = 0; i < s - 1; i++)
{
ext[i] = new double[s - 1];
}
int ext_c = 0, ext_r = 0;
for (int i = 0; i < s; i++)
{
if (i != row)
{
for (int j = 0; j < s; j++)
{ // Overflow on ext_c here
if (j != col) ext[ext_r][ext_c++] = mat[i][j];
}
ext_r++;
}
}
return ext;
};
您永远不会重置ext_c
,因此它的大小会不断增加到(s-1)*(s-1)
,这显然会溢出ext[]
数组。要解决此问题,您只需将内循环定义更改为:
for (int j = 0, ext_c = 0; j < s; j++)
至少有一个更改允许我在没有任何堆损坏错误的情况下运行您的项目。