新的C++堆损坏

C++ heap corruption on new

本文关键字:损坏 C++ 新的      更新时间:2023-10-16

我正在为函数的逼近编写简单的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)已被传递到内存中具有一些地址的函数中。这很奇怪,因为我没有初始化它。我调用了两次这个函数,第一次它运行得很好(好吧,至少它运行得好),但在第二次调用时它崩溃了。我不知道如何解决它。
有链接到整个项目:点击
我在MS Visual Studio 2013中使用Windows 7 x64。

更新
根据下面的一些评论,我应该提供一些补充信息
首先,对代码的质量表示抱歉。我只为自己写了两天
第二,当我说"在第二次调用"时,我的意思是,当我需要得到S的行列式时,我首先调用LU(我使用LU分解),并且它在没有任何崩溃的情况下工作。第二个调用是当我试图得到矩阵的逆时(同样,s)。当我在矩阵的[0,0]点调用detLU时(为了得到辅因子),我得到了这个崩溃
第三,如果我正确地从debagger获得信息,数组L和U在第二次调用时使用已经定义的内存地址传入函数。我不明白为什么,因为在LU调用之前,我刚刚写了"double**L;double**U;",没有任何初始化
如果有人向我解释我到底要做什么,我可以尝试提供一些额外的调试信息或测试。

发生堆损坏错误/崩溃的点通常只是过去某个其他时间/点发生实际堆溢出/下溢或其他内存错误的症状。这就是为什么堆损坏很难追踪的原因。

你有很多代码,所有的双指针都很难跟踪,但我确实注意到了一个潜在的问题:

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];

如果h小于10,则循环将溢出W[]。很可能在代码中的某个地方出现了缓冲区上溢/下溢,或者在释放内存后正在使用内存。代码的复杂性和设计使其很难一目了然。

使用原始双指针而不是简单的std::vector<std::vector<double>>有什么原因吗?这将删除所有手动内存管理代码,使代码更短、更简单,更重要的是消除堆损坏问题。

除非您应该仔细检查所有手动分配的内存大小是否正确,并且访问循环永远不会越界。

更新--我认为您的问题可能在于matrix.cpp:中extract()函数的缓冲区溢出

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++)

至少这一个更改使我能够在没有任何堆损坏错误的情况下运行您的项目。