APPCRASH(不在调试时)和使用 QtCreator 的分段错误 (C/C++)

APPCRASH (not when debugging) and Segmentation fault using QtCreator (C/C++)

我正在使用 QtCreator 编写我已经在 Matlab 上编写的算法。

编写这个程序时,我有两个错误。第一个 (APPCRASH) 在我正常构建和执行程序时出现,但在我尝试调试它 (Heisenbug) 时没有出现,它出现在函数 'matriceA' 上。我试图使变量可变并在其他函数上编写矩阵 A 项公式,希望这将停止编译器优化(我认为编译器优化可能会导致问题),但我无法解决问题.我没有尝试使用选项 -o0 编译项目,因为我的教授(这是一个大学项目)必须能够正常编译它(没有特定选项)。

第二个是 SISSEGV 分段错误。当代码到达 InpaintingColor 上的 "DestroyFloatArray(&b, width);" 时会发生这种情况。

这里是代码:

clanu_process.cpp(有点乱因为我试了很多东西...)

#include "clanu_process.h"
#include "iomanip"


void InpaintingColor(float **Rout, float **Gout, float **Bout, float **Rin, float **Gin, float **Bin, float **Mask, int width, int height, double param)
{
    cout << "1" << endl;
    float alphak = 0, bethak = 0, res = 0;
    float **b = 0, **xk = 0, **dk = 0, **rk = 0, **Ark = 0, **tmp1 = 0,**tmp2 = 0,**tmp3 = 0;
    Ark = AllocateFloatArray( width, height);
    tmp1 = AllocateFloatArray( width, height);
    tmp2 = AllocateFloatArray( width, height);
    tmp3 = AllocateFloatArray( width, height);
    xk = AllocateFloatArray( width, height);
    dk = AllocateFloatArray( width, height);
    rk = AllocateFloatArray( width, height);
    b = AllocateFloatArray( width, height);

    cout << "2" << endl;
    res = 1e8;
    matrixProductByScalar(b,1.0/(3.0*256),Rin,width,height);
    matrixDuplicate(xk, b, width, height);
    // APPCRASH error
    matriceA(Ark,xk,Mask,width,height);

    //More code

    // SIGSEGV error
    DestroyFloatArray(&b, width);
    DestroyFloatArray(&xk, width);
    DestroyFloatArray(&dk, width);
    DestroyFloatArray(&rk, width);
    DestroyFloatArray(&Ark, width);
    DestroyFloatArray(&tmp1, width);
    DestroyFloatArray(&tmp2, width);
    DestroyFloatArray(&tmp3, width);
}
float** matriceA(float **A, float **I, float **Masque, int N2, int N1){
    volatile bool bool_iplus = false, bool_imoins = false, bool_jmoins = false, bool_jplus = false;
    volatile int iplus = 0, imoins = 0, jplus = 0, jmoins = 0;

    for(int i = 1; i <= N1; i++){
        bool_iplus = i<N1;
        iplus = i+1 < N1 ? i+1 : N1;
        bool_imoins = i>1;
        imoins = i-1 > 1 ? i-1 : 1;

        for(int j = 1; j <= N2; j++){

            bool_jplus = j<N2;
            jplus = j+1 < N2 ? j+1 : N2;
            bool_jmoins = j>1;
            jmoins = j -1 > 1 ? j-1 : 1;
            if(Masque[i-1][j-1]!=0){
                //cout << "if - " << i << ", " << j<< endl;
                A[i-1][j-1] = (1.0/36)*(16*I[i-1][j-1]
                 + 4*(
                    (bool_iplus?I[iplus-1][j-1]:0)
                    + (bool_imoins?I[imoins-1][j-1]:0)
                    + (bool_jplus?I[i-1][jplus-1]:0)
                    + (bool_jmoins?I[i-1][jmoins-1]:0)
                 )+(
                    (bool_iplus&&bool_jplus?I[iplus-1][jplus-1]:0)
                    + (bool_imoins&&bool_jplus?I[imoins-1][jplus-1]:0)
                    + (bool_imoins&&bool_jmoins?I[imoins-1][jmoins-1]:0))
                 + (bool_iplus&&bool_jmoins?I[iplus-1][jmoins-1]:0));
            }else{
                //cout << "else - " << i << ", " << j << endl;
                A[i-1][j-1]=
                    -(1.0*N1*N2)*(
                        -8.0*I[i-1][j-1]
                        + I[iplus-1][j-1]
                        + I[imoins-1][j-1]
                        + I[i-1][jplus-1]
                        + I[i-1][jmoins-1]
                        + I[iplus-1][jplus-1]
                        + I[imoins-1][jplus-1]
                        + I[imoins-1][jmoins-1]
                        + I[iplus-1][jmoins-1]);
            }
        }
    }
    return A;
}

函数 AllocateFloatArray 和 DestroyFloatArray

float ** AllocateFloatArray(int width, int height)
{
    float ** r = new float*[width];
    for(int i=0; i<width; i++)
        r[i] = new float[height];
    return r;
}

void DestroyFloatArray(float ***a, int width)
{
    if( *a == 0 ) return;
    for(int i=0; i<width; i++)
        delete[] a[0][i];
    delete[] *a;
    *a = 0;
}

感谢您的宝贵时间。

我不确定这是否是您遇到问题的原因,但是...

你的函数 "Matrix operations"(sum()matrixSubstraction()matrixAddition()matrixProductByElement()matrixProductByScalar()matrixDuplicate())第一个索引从零到 width,第二个索引从零到 height

如果我没记错的话,这是正确的,并且与 allocation/deallocation(AllocateFloatArray()DestroyFloatArray())一致。

但是看看这两个matriceA()函数;它们被定义为

float** matriceA(float **A, float **I, int N2, int N1)
float** matriceA(float **A, float **I, float **Masque, int N2, int N1)

在这两个函数中,第一个索引范围从零到 N1,第二个索引范围从零到 N2;举个例子

for(int i = 1; i <= N1; i++){
// ...
   for(int j = 1; j <= N2; j++){
   // ...
      A[i-1][j-1] = (1.0/36)*(16*I[i-1][j-1] // ...

很好。但是你这样调用matriceA()

matriceA(Ark,rk,Mask,width,height);

简而言之:您将矩阵分配为 width * height 矩阵;您的 "matrix operations" 将它们用作 width * height 矩阵,但您的 matriceA() 函数将它们用作 height * width.

摧毁记忆的绝妙方式。

我想解决方案可能是

1) 在 matriceA() 定义

中切换 N1N2

2) 或在 matriceA() 调用

中切换 widthheight

p.s.: 对不起我的英语不好