new 上的 C++ 堆损坏

C++ heap corruption on new

我正在为函数的逼近编写简单的 ANN(神经网络)。我崩溃了,消息是:"Heap corrupted"。我发现很少有关于如何解决它的建议,但没有任何帮助。 我在这个函数的第一行出错:

 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)已被传递给内存中的一些地址。这很奇怪,因为我没有初始化它。我调用此函数两次,第一次它运行良好(好吧,至少它运行良好),但第二次调用时它崩溃了。我不知道如何解决它。
整个项目有link:CLICK
我在 MS Visual Studio 2013 Windows 7 x64 下工作。

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

堆损坏 error/crash 通常只是实际堆 overflow/underflow 或过去某个其他 time/point 的其他内存错误的症状。这就是为什么堆损坏难以追踪的原因。

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

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[]。可能是代码中某处有缓冲区 overflow/underflow 或在释放内存后正在使用内存。代码的复杂性和设计让人很难一目了然。

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

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

Update -- 我认为您的问题可能在于 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++)

至少那一项更改让我 运行 您的项目没有任何堆损坏错误。