c - 如何克服c中的双重释放或损坏(出)中止(核心转储)

标签 c double-pointer double-free

我正在尝试创建一个 Zoom_image 函数,它使用离散傅里叶变换来缩放灰度图像。如果图像大小小于或等于 4*4 但大小增加,我包含的代码可以工作。它给出“双重释放或损坏(出)中止(核心转储)”错误

我已经尝试过我的代码的 fft_d 和 ifft_2d 函数,如果输入大小很小,它可以工作;如果输入大小很大,它会给出上述错误

#include<math.h>
#include<stdio.h>
#include<stdlib.h>
struct complex{
      float real;
      float im;
};
typedef struct complex complex;
complex w(int i, int n) {
      complex result;
      result.real = cos(2*M_PI*i/n);
      result.im = -sin(2*M_PI*i/n);
      return result;
}
complex wp(int i, int n) {
      complex result;
      result.real = cos(2*M_PI*i/n);
      result.im = sin(2*M_PI*i/n);
      return result;
}
complex mul(complex a, complex b) {
      complex result;
      result.real = a.real*b.real - a.im*b.im;
      result.im = a.real*b.im + b.real*a.im;
      return result;
}
complex divi(complex a, complex b) {
      complex result;
      result.real = (a.real*b.real + a.im*b.im)/(b.real*b.real + b.im*b.im);
      result.im = (-a.real*b.im + b.real*a.im)/(b.real*b.real + b.im*b.im);
      return result;
}
complex add(complex a, complex b) {
      complex result;
      result.real = a.real+b.real ;
      result.im = a.im+b.im;
      return result;
}
complex sub(complex a, complex b) {
      complex result;
      result.real = a.real - b.real;
      result.im = a.im - b.im;
      return result;
}
void printComplex(complex var) {
      printf("%f i%f\n",var.real,var.im);
}
void printComplexS(complex var) {
      printf("%f i%f",var.real,var.im);
}

#include<stdio.h>
#include<stdlib.h>
#include"complex.h"
static int gb=0;
complex* _fft(complex *arr, int size, int step, int index) {
    if(size == 2) {
        complex *result;
        result = (complex*)malloc(size*sizeof(complex));
        result[0] = add(arr[index], arr[index+step]);
        result[1] = sub(arr[index], arr[index+step]);
        return result;
    }
    else {
        int i;
        complex *even, *odd, *result, *mull;
        even = _fft(arr, size/2, step*2, index);
        odd = _fft(arr, size/2, step*2, index+step);
        result = (complex*)malloc(size*sizeof(complex));
        mull = (complex*)malloc(size/2*sizeof(complex));
        for(i=0;i<size/2;i++) {
            mull[i] = mul(odd[i], w(i,size));
        }
        for(i=0;i<size/2;i++)
            result[i] = add(even[i], mull[i]);
        for(;i<size;i++)
            result[i] = sub(even[i - size/2], mull[i - size/2]);
        free(even);
        free(odd);
        free(mull);
        return result;
    }
}
complex* fft(complex *arr, int size) {
      return (complex*)_fft(arr, size, 1, 0);
}
complex* _ifft(complex *arr, int size, int step, int index) {
      if(size == 2) {
            complex *result;
            result = (complex*)malloc(size*sizeof(complex));
            result[0] = add(arr[index], arr[index+step]);
            result[1] = sub(arr[index], arr[index+step]);
            return result;
      }
      else {
            int i;
            complex *even, *odd, *result, *mull;
            even = _ifft(arr, size/2, step*2, index);
            odd = _ifft(arr, size/2, step*2, index+step);
            result = (complex*)malloc(size*sizeof(complex));
            mull = (complex*)malloc(size/2*sizeof(complex));
            for(i=0;i<size/2;i++)
                  mull[i] = mul(odd[i], wp(i,size));
            for(i=0;i<size/2;i++)
                  result[i] = add(even[i], mull[i]);
            for(;i<size;i++)
                  result[i] = sub(even[i - size/2], mull[i - size/2]);
            free(even);
            free(odd);
            free(mull);
            return result;
      }
}
complex* ifft(complex *arr, int size) {
    complex *re = _ifft(arr, size, 1, 0);
    for(int i=0;i<size;i++){
        re[i].real=re[i].real/size;
        re[i].im=re[i].im/size;
    }
    return re;
}
complex** transpose(complex **src, int n, int m) {
    complex **result, ***re;
    result=(complex**)malloc(sizeof(complex*)*m);
    for(int i=0;i<m;i++) {
        result[i]=(complex*)malloc(sizeof(complex)*n);
        for(int j=0;j<n;j++)
            result[i][j]=src[j][i];
    }
    re=(complex***)&result;
    return (complex**)*re;
}
complex** fft_2d(complex** arr, int n, int m) {
    complex **arrR, ***r, *temp;
    int i, j;
    arrR = (complex**)malloc(sizeof(complex*));
    for(i=0;i<n;i++) {
        arrR[i]=(complex*)fft(arr[i],m);
        printf("%d ",i);
    }
    arrR=(complex**)transpose(arrR,n,m);
    malloc(0);
    for(i=0;i<m;i++)
        arrR[i]=(complex*)fft(arrR[i],n);
    arrR=transpose(arrR,n,m);
    r=(complex***)&arrR;
    return (complex**)*r;
}
complex** ifft_2d(complex** arr, int n, int m) {
    complex **arrR, ***r, *temp;
    int i, j;
    arrR = (complex**)malloc(sizeof(complex*));
    for(i=0;i<n;i++)
        arrR[i]=(complex*)ifft(arr[i],m);
    arrR=(complex**)transpose(arrR,n,m);
    malloc(0);
    for(i=0;i<m;i++)
        arrR[i]=(complex*)ifft(arrR[i],n);
    arrR=transpose(arrR,n,m);
    r=(complex***)&arrR;
    return (complex**)*r;
}

unsigned int** zoom_img(unsigned int **img, int col, int row, int r_col, int r_row) {
    int i, j;
    complex **mat=(complex**)malloc(sizeof(complex*)*col), **re;
    complex **new_re=(complex**)malloc(sizeof(complex*)*(col+2*r_col)), **u;
    unsigned int **result=(unsigned int**)malloc(sizeof(unsigned int*)*(col + 2*r_col)), ***z;
    for(i=0;i<col;i++)
        mat[i]=(complex*)malloc(sizeof(complex)*row);
    for (i=0;i<col;i++) {
        for (j=0;j<row;j++) {
            mat[i][j].real = (float)pow(-1, i+j)*(float)img[i][j];
            mat[i][j].im=0;
        }
    }
    re = (complex**)fft_2d(mat, col, row);
    for(i=0;i<(col+2*r_col);i++)
        new_re[i]=(complex*)malloc(sizeof(complex)*(row+2*r_row));
    for(i=0;i<(col+2*r_col);i++) {
        for(j=0;j<(row+2*r_row);j++) {
            if(i<r_col || i>r_col+col-1 || j<r_row || j>r_row+row-1) {
                new_re[i][j].real = 0;
                new_re[i][j].im = 0;
            }
            else
                new_re[i][j]=re[i-r_col][j-r_row];
        }
    }
    u = (complex**)ifft_2d(new_re, col+2*r_col, row + 2*r_row);
    for(i=0;i<(col+2*r_col);i++) {
        result[i]=(unsigned int*)malloc(sizeof(unsigned int)*(row+2*r_row));
        for(j=0;j<(row+2*r_row);j++) {
            result[i][j] = (unsigned int)u[i][j].real;
        }
    }
    z=&result;
    return *z;
}

int main() {
    unsigned int i, j, **arr=(unsigned int**)malloc(sizeof(unsigned int*)*2), **result;
    for(i=0;i<2;i++) {
        arr[i]=(unsigned int*)malloc(sizeof(unsigned int)*2);
        for(j=0;j<2;j++) {
             arr[i][j] = i+j +1;
        }
    }
    result = zoom_img(arr,2,2,2,2);
    return 0;
}/*
int main() {
    complex **arr, **result, **re;
    arr=(complex**)malloc(sizeof(complex*)*4);
    for (int i = 0; i < 4; i++) {
        arr[i]=(complex*)malloc(sizeof(complex)*4);
        for (int j = 0; j < 4; j++) {
            arr[i][j].real = i*j+1.2;
            arr[i][j].im=0;
        }
    }
    result = (complex**)fft_2d(arr,4,4);
    //malloc(0);
    re = (complex**)ifft_2d(result,4,4);
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            printf("(%2f) ", arr[i][j].real);
            printComplexS(result[i][j]);
            printf(" (%2f) ",re[i][j].real);
        }
        printf("\n");
    }
      return 0;
}*/

最佳答案

该代码有几个问题。

complex** ifft_2d(complex** arr, int n, int m) {
    complex **arrR, ***r;
    int i;

然后你分配的太少了:

    arrR = (complex**)malloc(sizeof(complex*));

上面的行应该是malloc(sizeof(complex*) * n)。如果没有 *n ,下一行会导致未定义的行为(缓冲区溢出):

    for(i=0;i<n;i++)
        arrR[i]=(complex*)ifft(arr[i],m);

然后还有这行奇怪的一行,这是为什么呢?

    malloc(0);

那么函数的结尾很奇怪(为什么不简单地返回 arrR?):

    r=(complex***)&arrR;
    return (complex**)*r;

接下来,递归代码(_ifft 和 _fft)假设 size 是 2 的幂,否则会陷入无限递归。您应该验证输入。至少断言:

assert(n >= 2);
assert(((n-1) & n ) == 0); // for positive n, assert that it is a power of 2

通过这一行,您可以看到 zoom_img 违反了该行中的假设:

u = (complex**)ifft_2d(new_re, col+2*r_col, row + 2*r_row);

请注意,在未注释的 main 中,col==2、row==2、r_col==2、r_row==2 的结果是 size == 6,这不是2 的幂。

一个较小的问题是性能。该代码过度使用了malloc,而不是重用同一 block 内存,并查看它的不同区域。这就是经典 FFT 的作用。经典的FFT也不使用这样的递归,而是使用迭代。

关于c - 如何克服c中的双重释放或损坏(出)中止(核心转储),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55434259/

相关文章:

c++ - C/C++ 中的指针实际上是如何存储地址的?

无法在 getline() while 循环之外打印 char**

c - 在用 C 实现的链表中使用单指针和双指针

c - C 程序读取文件并转换其字符会产生双重释放或损坏错误

c - *** 错误 : double free or corruption (out): 0x00007fffe3465010 ***. 警告 : Corrupted shared library list: 0x7ffea4000920 ! = 0x7ffff7ffd9d8

c - 在c中排序5d数组

c - 通过 C 中的中心函数管理管道

c - "double free"是什么意思?

c - which function takes no constant parameters similar to system(constant char) in linux

c++ - 双指针作为参数